From 4c551e6612e3dec57882b00264fdbe4c12153a8d Mon Sep 17 00:00:00 2001 From: junsuPark Date: Fri, 8 Mar 2024 11:13:08 +0900 Subject: [PATCH 001/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20home?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/aliens/dms/android/feature/main/home/HomeScreen.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/home/HomeScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/home/HomeScreen.kt index 2419a5f57..645ef9346 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/home/HomeScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/home/HomeScreen.kt @@ -193,7 +193,7 @@ internal fun HomeScreen( onNextDay = { onSelectedDateChange(uiState.selectedDate.plusDays(1)) }, onPreviousDay = { onSelectedDateChange(uiState.selectedDate.minusDays(1)) }, ) - Spacer(modifier = Modifier.height(92.dp)) + Spacer(modifier = Modifier.height(76.dp)) } } } From b0bf919de699155cb0470704d7deca0bf0733301 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Fri, 8 Mar 2024 11:50:05 +0900 Subject: [PATCH 002/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20studyroom=20l?= =?UTF-8?q?ist?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../studyroom/list/StudyRoomListScreen.kt | 72 ++++++++----------- 1 file changed, 30 insertions(+), 42 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/studyroom/list/StudyRoomListScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/studyroom/list/StudyRoomListScreen.kt index e5349355e..8d2d0d1a1 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/studyroom/list/StudyRoomListScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/studyroom/list/StudyRoomListScreen.kt @@ -3,10 +3,8 @@ package team.aliens.dms.android.feature.studyroom.list import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row -import androidx.compose.foundation.layout.Spacer 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.lazy.LazyRow import androidx.compose.foundation.lazy.items @@ -15,28 +13,27 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.SheetValue import androidx.compose.material3.Text -import androidx.compose.material3.rememberBottomSheetScaffoldState -import androidx.compose.material3.rememberStandardBottomSheetState +import androidx.compose.material3.rememberModalBottomSheetState 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.rememberCoroutineScope -import androidx.compose.runtime.setValue 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.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import kotlinx.coroutines.launch import team.aliens.dms.android.core.designsystem.Button import team.aliens.dms.android.core.designsystem.ButtonDefaults -import team.aliens.dms.android.core.designsystem.DmsBottomSheetScaffold +import team.aliens.dms.android.core.designsystem.DmsScaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar +import team.aliens.dms.android.core.designsystem.ModalBottomSheet import team.aliens.dms.android.core.designsystem.OutlinedButton import team.aliens.dms.android.core.designsystem.VerticallyFadedLazyColumn import team.aliens.dms.android.core.ui.DefaultHorizontalSpace @@ -58,27 +55,18 @@ internal fun StudyRoomListScreen( navigator: StudyRoomNavigator, viewModel: StudyRoomListViewModel = hiltViewModel(), ) { - // TODO: val toastState = rememberToastState() val uiState by viewModel.stateFlow.collectAsStateWithLifecycle() - val scope = rememberCoroutineScope() - - val scaffoldState = rememberBottomSheetScaffoldState( - bottomSheetState = rememberStandardBottomSheetState( - skipHiddenState = false, - initialValue = SheetValue.Hidden, - ), - ) - - var newlySelectedAvailableStudyRoomTime by remember { - mutableStateOf(null) + val (shouldShowTimeFilterBottomSheet, onShouldShowTimeFilterBottomSheetChange) = remember { + mutableStateOf(false) } - DmsBottomSheetScaffold( - modifier = modifier, - scaffoldState = scaffoldState, - sheetSwipeEnabled = false, - sheetContent = { + val sheetState = rememberModalBottomSheetState() + if (shouldShowTimeFilterBottomSheet) { + ModalBottomSheet( + onDismissRequest = { onShouldShowTimeFilterBottomSheetChange(false) }, + sheetState = sheetState, + ) { Column( modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(DefaultVerticalSpace), @@ -112,7 +100,11 @@ internal fun StudyRoomListScreen( } else { OutlinedButton( onClick = { - newlySelectedAvailableStudyRoomTime = availableStudyRoomTime + viewModel.postIntent( + StudyRoomListIntent.UpdateSelectedAvailableStudyRoomTime( + availableStudyRoomTime, + ), + ) }, colors = ButtonDefaults.outlinedGrayButtonColors(), ) { @@ -133,23 +125,23 @@ internal fun StudyRoomListScreen( .fillMaxWidth() .horizontalPadding(), onClick = { - if (newlySelectedAvailableStudyRoomTime != null) { - if (newlySelectedAvailableStudyRoomTime != uiState.selectedAvailableStudyRoomTime) { - viewModel.postIntent( - StudyRoomListIntent.UpdateSelectedAvailableStudyRoomTime( - availableStudyRoomTime = newlySelectedAvailableStudyRoomTime!!, - ), - ) - } - } - scope.launch { scaffoldState.bottomSheetState.hide() } + scope.launch { sheetState.hide() } }, ) { Text(text = stringResource(id = R.string.accept)) } - Spacer(modifier = Modifier.height(52.dp)) } - }, + } + } + + LaunchedEffect(sheetState.currentValue) { + if (sheetState.currentValue == SheetValue.Hidden) { + onShouldShowTimeFilterBottomSheetChange(false) + } + } + + DmsScaffold( + modifier = modifier, topBar = { DmsTopAppBar( navigationIcon = { @@ -188,11 +180,7 @@ internal fun StudyRoomListScreen( .fillMaxWidth() .horizontalPadding(), availableStudyRoomTime = uiState.selectedAvailableStudyRoomTime, - onFilterButtonClick = { - scope.launch { - scaffoldState.bottomSheetState.expand() - } - }, + onFilterButtonClick = { onShouldShowTimeFilterBottomSheetChange(true) }, ) uiState.studyRooms?.let { studyRooms -> VerticallyFadedLazyColumn( From 166ab0432817bf35f1fc9165be73402ded670dec Mon Sep 17 00:00:00 2001 From: chlgkdms Date: Wed, 13 Mar 2024 22:21:11 +0900 Subject: [PATCH 003/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::signin=20?= =?UTF-8?q?=EC=A3=BC=EC=84=9D=20=EC=A0=9C=EA=B1=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/aliens/dms/android/feature/signin/SignInScreen.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/signin/SignInScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/signin/SignInScreen.kt index 4c422ad91..14d06c31e 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/signin/SignInScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/signin/SignInScreen.kt @@ -7,6 +7,7 @@ import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.imePadding import androidx.compose.foundation.layout.padding import androidx.compose.foundation.rememberScrollState @@ -17,6 +18,7 @@ import androidx.compose.material3.ProvideTextStyle import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults +import androidx.compose.material3.VerticalDivider import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -32,6 +34,7 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.input.ImeAction import androidx.compose.ui.text.input.KeyboardType import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination @@ -248,8 +251,6 @@ private fun UnauthorizedActions( .clickable(onClick = onSignUp), text = stringResource(id = R.string.sign_in_sign_up), ) - // TODO: v1.2.0 - /* VerticalDivider( modifier = Modifier.height(12.dp), color = DmsTheme.colorScheme.onSurfaceVariant, @@ -270,7 +271,6 @@ private fun UnauthorizedActions( .clickable(onClick = onResetPassword), text = stringResource(id = R.string.sign_in_reset_password), ) - */ } } } From 80b6312cd7bcf579d81c409d6ab3dc9b1b002a01 Mon Sep 17 00:00:00 2001 From: Junsu Park <101160207+JunJaBoy@users.noreply.github.com> Date: Thu, 14 Mar 2024 08:39:25 +0900 Subject: [PATCH 004/129] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 0d5313c2c..9f9eeb6be 100644 --- a/README.md +++ b/README.md @@ -23,6 +23,9 @@ DMS는 기숙사를 위한 편의 시스템을 목표로 하고 있기 때문에

+# Project structure +![image](https://github.com/team-aliens/DMS-Android/assets/101160207/f53fd04e-d29f-41d2-9cf3-60f16645ab4b) + # Contributors
From 7ccbf4c4054d6da0aeacff3e4aa00ad867600a5d Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 14 Mar 2024 11:57:38 +0900 Subject: [PATCH 005/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20OutingAvailab?= =?UTF-8?q?leTimeResponse=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../outing/model/OutingAvailableTimeResponse.kt | 15 +++++++++++++++ 1 file changed, 15 insertions(+) create mode 100644 network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt new file mode 100644 index 000000000..ad950770e --- /dev/null +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt @@ -0,0 +1,15 @@ +package team.aliens.dms.android.network.outing.model + +import com.google.gson.annotations.SerializedName + +data class OutingAvailableTimeResponse( + @SerializedName("outing_available_time") val availableTimes: List, +) { + data class AvailableTimeResponse( + @SerializedName("outing_available_time_id") val outingAvailableTimeId: String, + @SerializedName("outing_time") val startTime: String, + @SerializedName("arrival_time") val endTime: String, + @SerializedName("enabled") val available: Boolean, + @SerializedName("day_of_week") val dayOfWeek: String, + ) +} From 6d82b643cca979423ab712aa9dce3da345f2622f Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 14 Mar 2024 12:08:05 +0900 Subject: [PATCH 006/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20ApplyOutingRe?= =?UTF-8?q?quest=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network/outing/model/ApplyOutingRequest.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt new file mode 100644 index 000000000..e37f5966c --- /dev/null +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt @@ -0,0 +1,13 @@ +package team.aliens.dms.android.network.outing.model + +import com.google.gson.annotations.SerializedName +import java.util.UUID + +data class ApplyOutingRequest( + @SerializedName("out_at") val date: String, + @SerializedName("outing_time") val startTime: String, + @SerializedName("arrival_time") val endTime: String, + @SerializedName("outing_type_title") val type: String, + @SerializedName("reason") val reason: String?, + @SerializedName("companion_ids") val followerIds: List, +) From ee73423d49d1a839360e0b48f0adb6c7dd52a6e1 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 14 Mar 2024 12:11:19 +0900 Subject: [PATCH 007/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20ApplyOutingRe?= =?UTF-8?q?sponse=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/network/outing/model/ApplyOutingResponse.kt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingResponse.kt diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingResponse.kt new file mode 100644 index 000000000..1596e1aed --- /dev/null +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingResponse.kt @@ -0,0 +1,7 @@ +package team.aliens.dms.android.network.outing.model + +import com.google.gson.annotations.SerializedName + +data class ApplyOutingResponse( + @SerializedName("outing_application_id") val applicationId: String, +) From 1ee677746361e0427d09ecd75d02c287256da991 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 14 Mar 2024 12:22:43 +0900 Subject: [PATCH 008/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20FetchOutingAp?= =?UTF-8?q?plicationDetailsResponse=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FetchOutingApplicationDetailsResponse.kt | 20 +++++++++++++++++++ 1 file changed, 20 insertions(+) create mode 100644 network/src/main/java/team/aliens/dms/android/network/outing/model/FetchOutingApplicationDetailsResponse.kt diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchOutingApplicationDetailsResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchOutingApplicationDetailsResponse.kt new file mode 100644 index 000000000..547bf01cc --- /dev/null +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchOutingApplicationDetailsResponse.kt @@ -0,0 +1,20 @@ +package team.aliens.dms.android.network.outing.model + +import com.google.gson.annotations.SerializedName +import java.util.UUID + +data class FetchOutingApplicationDetailsResponse( + @SerializedName("outing_time") val startTime: String, + @SerializedName("arrival_time") val endTime: String, + @SerializedName("outing_status") val status: String, + @SerializedName("reason") val reason: String?, + @SerializedName("outing_type") val type: String, + @SerializedName("students") val student: List, +) { + data class StudentResponse( + @SerializedName("id") val id: UUID, + @SerializedName("name") val name: String, + @SerializedName("gcn") val gradeClassNumber: String, + @SerializedName("room_number") val roomNumber: String, + ) +} From f21dd55b9cb853a5f3c276ba5e11f6b0a521539a Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 14 Mar 2024 12:27:08 +0900 Subject: [PATCH 009/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20FetchCurrentA?= =?UTF-8?q?ppliedOutingApplicationResponse=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../FetchCurrentAppliedOutingApplicationResponse.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt new file mode 100644 index 000000000..15f34df80 --- /dev/null +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt @@ -0,0 +1,13 @@ +package team.aliens.dms.android.network.outing.model + +import com.google.gson.annotations.SerializedName + +data class FetchCurrentAppliedOutingApplicationResponse( + @SerializedName("out_at") val date: String, + @SerializedName("outing_type") val type: String, + @SerializedName("status") val status: String, + @SerializedName("outing_time") val startTime: String, + @SerializedName("arrival_time") val endTime: String, + @SerializedName("reason") val reason: String?, + @SerializedName("outing_companions") val followerNames: List, +) From 47c9fa444e48a02b119c8410a8f16471f1b7d664 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 14 Mar 2024 14:17:51 +0900 Subject: [PATCH 010/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20FetchOutingTy?= =?UTF-8?q?pesResponse=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network/outing/model/FetchOutingTypesResponse.kt | 7 +++++++ 1 file changed, 7 insertions(+) create mode 100644 network/src/main/java/team/aliens/dms/android/network/outing/model/FetchOutingTypesResponse.kt diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchOutingTypesResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchOutingTypesResponse.kt new file mode 100644 index 000000000..eaaa75b13 --- /dev/null +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchOutingTypesResponse.kt @@ -0,0 +1,7 @@ +package team.aliens.dms.android.network.outing.model + +import com.google.gson.annotations.SerializedName + +data class FetchOutingTypesResponse( + @SerializedName("titles") val titles: String, +) From f44e6a1ff56142e6fe674958e08085de3572a99f Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 14 Mar 2024 16:18:51 +0900 Subject: [PATCH 011/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20netw?= =?UTF-8?q?ork=20data=20source?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../datasource/OutingNetworkDataSource.kt | 19 +++++++++++ .../datasource/OutingNetworkDataSourceImpl.kt | 34 +++++++++++++++++++ 2 files changed, 53 insertions(+) create mode 100644 network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSource.kt create mode 100644 network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSourceImpl.kt diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSource.kt b/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSource.kt new file mode 100644 index 000000000..326b6b0a9 --- /dev/null +++ b/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSource.kt @@ -0,0 +1,19 @@ +package team.aliens.dms.android.network.outing.datasource + +import retrofit2.Response +import team.aliens.dms.android.network.outing.model.ApplyOutingRequest +import team.aliens.dms.android.network.outing.model.ApplyOutingResponse +import team.aliens.dms.android.network.outing.model.FetchCurrentAppliedOutingApplicationResponse +import team.aliens.dms.android.network.outing.model.FetchOutingApplicationDetailsResponse +import team.aliens.dms.android.network.outing.model.FetchOutingTypesResponse +import team.aliens.dms.android.network.outing.model.OutingAvailableTimeResponse +import java.util.UUID + +abstract class OutingNetworkDataSource { + abstract fun fetchOutingAvailableTime(type: String): OutingAvailableTimeResponse + abstract fun applyOuting(req: ApplyOutingRequest): ApplyOutingResponse + abstract fun fetchOutingApplicationDetails(applicationId: UUID): FetchOutingApplicationDetailsResponse + abstract fun fetchCurrentAppliedOutingApplication(): FetchCurrentAppliedOutingApplicationResponse + abstract fun cancelOuting(applicationId: UUID): Response + abstract fun fetchOutingTypes(keyword: String?): FetchOutingTypesResponse +} diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSourceImpl.kt b/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSourceImpl.kt new file mode 100644 index 000000000..d87d30637 --- /dev/null +++ b/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSourceImpl.kt @@ -0,0 +1,34 @@ +package team.aliens.dms.android.network.outing.datasource + +import retrofit2.Response +import team.aliens.dms.android.network.outing.apiservice.OutingApiService +import team.aliens.dms.android.network.outing.model.ApplyOutingRequest +import team.aliens.dms.android.network.outing.model.ApplyOutingResponse +import team.aliens.dms.android.network.outing.model.FetchCurrentAppliedOutingApplicationResponse +import team.aliens.dms.android.network.outing.model.FetchOutingApplicationDetailsResponse +import team.aliens.dms.android.network.outing.model.FetchOutingTypesResponse +import team.aliens.dms.android.network.outing.model.OutingAvailableTimeResponse +import java.util.UUID +import javax.inject.Inject + +class OutingNetworkDataSourceImpl @Inject constructor( + private val outingApiService: OutingApiService, +) : OutingNetworkDataSource() { + override fun fetchOutingAvailableTime(type: String): OutingAvailableTimeResponse = + outingApiService.fetchOutingAvailableTime(type) + + override fun applyOuting(req: ApplyOutingRequest): ApplyOutingResponse = + outingApiService.applyOuting(req) + + override fun fetchOutingApplicationDetails(applicationId: UUID): FetchOutingApplicationDetailsResponse = + outingApiService.fetchOutingApplicationDetails(applicationId) + + override fun fetchCurrentAppliedOutingApplication(): FetchCurrentAppliedOutingApplicationResponse = + outingApiService.fetchCurrentAppliedOutingApplication() + + override fun cancelOuting(applicationId: UUID): Response = + outingApiService.cancelOuting(applicationId) + + override fun fetchOutingTypes(keyword: String?): FetchOutingTypesResponse = + outingApiService.fetchOutingTypes(keyword) +} From ea3222dcf95e6d5668c0af59dcd78a5fe07cd929 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 14 Mar 2024 16:19:07 +0900 Subject: [PATCH 012/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20api?= =?UTF-8?q?=20service?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../outing/apiservice/OutingApiService.kt | 42 +++++++++++++++++++ 1 file changed, 42 insertions(+) create mode 100644 network/src/main/java/team/aliens/dms/android/network/outing/apiservice/OutingApiService.kt diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/apiservice/OutingApiService.kt b/network/src/main/java/team/aliens/dms/android/network/outing/apiservice/OutingApiService.kt new file mode 100644 index 000000000..cabc2e415 --- /dev/null +++ b/network/src/main/java/team/aliens/dms/android/network/outing/apiservice/OutingApiService.kt @@ -0,0 +1,42 @@ +package team.aliens.dms.android.network.outing.apiservice + +import retrofit2.Response +import retrofit2.http.DELETE +import retrofit2.http.GET +import retrofit2.http.POST +import retrofit2.http.Path +import retrofit2.http.Query +import team.aliens.dms.android.network.outing.model.ApplyOutingRequest +import team.aliens.dms.android.network.outing.model.ApplyOutingResponse +import team.aliens.dms.android.network.outing.model.FetchCurrentAppliedOutingApplicationResponse +import team.aliens.dms.android.network.outing.model.FetchOutingApplicationDetailsResponse +import team.aliens.dms.android.network.outing.model.FetchOutingTypesResponse +import team.aliens.dms.android.network.outing.model.OutingAvailableTimeResponse +import java.util.UUID + +interface OutingApiService { + + @GET("/outings/available-time") + fun fetchOutingAvailableTime(type: String): OutingAvailableTimeResponse + + @POST("/outings") + fun applyOuting(req: ApplyOutingRequest): ApplyOutingResponse + + @POST("/outings/{outing-application-id}") + fun fetchOutingApplicationDetails( + @Path("outing-application-id") applicationId: UUID, + ): FetchOutingApplicationDetailsResponse + + @GET("/outings/my") + fun fetchCurrentAppliedOutingApplication(): FetchCurrentAppliedOutingApplicationResponse + + @DELETE("/outing/{outing-application-id}") + fun cancelOuting( + @Path("outing-application-id") applicationId: UUID, + ): Response + + @GET("/outing/types") + fun fetchOutingTypes( + @Query("keyword") keyword: String?, + ): FetchOutingTypesResponse +} From 671b288550a9f9be34def95606d4ab99723164a6 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 14 Mar 2024 16:19:12 +0900 Subject: [PATCH 013/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20api?= =?UTF-8?q?=20service=20module?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network/outing/di/ApiServiceModule.kt | 21 +++++++++++++++++++ 1 file changed, 21 insertions(+) create mode 100644 network/src/main/java/team/aliens/dms/android/network/outing/di/ApiServiceModule.kt diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/di/ApiServiceModule.kt b/network/src/main/java/team/aliens/dms/android/network/outing/di/ApiServiceModule.kt new file mode 100644 index 000000000..aa0d14f25 --- /dev/null +++ b/network/src/main/java/team/aliens/dms/android/network/outing/di/ApiServiceModule.kt @@ -0,0 +1,21 @@ +package team.aliens.dms.android.network.outing.di + +import dagger.Module +import dagger.Provides +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import retrofit2.Retrofit +import team.aliens.dms.android.core.network.di.GlobalRetrofitClient +import team.aliens.dms.android.network.outing.apiservice.OutingApiService +import javax.inject.Singleton + +@InstallIn(SingletonComponent::class) +@Module +internal object ApiServiceModule { + + @Singleton + @Provides + fun provideOutingApiService( + @GlobalRetrofitClient retrofit: Retrofit, + ): OutingApiService = retrofit.create(OutingApiService::class.java) +} From e990cf64ff5039d7b2d99202ce6b8386f452354c Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 14 Mar 2024 16:19:25 +0900 Subject: [PATCH 014/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20repo?= =?UTF-8?q?sitory=20impl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/data/outing/di/RepositoryModule.kt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 data/src/main/java/team/aliens/dms/android/data/outing/di/RepositoryModule.kt diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/di/RepositoryModule.kt b/data/src/main/java/team/aliens/dms/android/data/outing/di/RepositoryModule.kt new file mode 100644 index 000000000..d71005337 --- /dev/null +++ b/data/src/main/java/team/aliens/dms/android/data/outing/di/RepositoryModule.kt @@ -0,0 +1,18 @@ +package team.aliens.dms.android.data.outing.di + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import team.aliens.dms.android.data.outing.repository.OutingRepository +import team.aliens.dms.android.data.outing.repository.OutingRepositoryImpl +import javax.inject.Singleton + +@InstallIn(SingletonComponent::class) +@Module +abstract class RepositoryModule { + + @Binds + @Singleton + abstract fun bindOutingRepository(impl: OutingRepositoryImpl): OutingRepository +} From 12e75c3a7b6214ec5910b37ff2ba9b6f9f040816 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 14 Mar 2024 16:19:30 +0900 Subject: [PATCH 015/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20repo?= =?UTF-8?q?sitory?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/data/outing/repository/OutingRepository.kt | 5 +++++ .../data/outing/repository/OutingRepositoryImpl.kt | 9 +++++++++ 2 files changed, 14 insertions(+) create mode 100644 data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt create mode 100644 data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt new file mode 100644 index 000000000..900a73d28 --- /dev/null +++ b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt @@ -0,0 +1,5 @@ +package team.aliens.dms.android.data.outing.repository + +abstract class OutingRepository { + +} diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt new file mode 100644 index 000000000..776dda0b9 --- /dev/null +++ b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt @@ -0,0 +1,9 @@ +package team.aliens.dms.android.data.outing.repository + +import javax.inject.Inject + +class OutingRepositoryImpl @Inject constructor( + private val outingNetworkDataSource: OutingNetworkDataSource, +) : OutingRepository() { + +} From a8dc4aa7850f5290e8c7b51d56450cc869c2444a Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 14 Mar 2024 20:10:41 +0900 Subject: [PATCH 016/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20datasourcemod?= =?UTF-8?q?ule?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network/outing/di/DataSourceModule.kt | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+) create mode 100644 network/src/main/java/team/aliens/dms/android/network/outing/di/DataSourceModule.kt diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/di/DataSourceModule.kt b/network/src/main/java/team/aliens/dms/android/network/outing/di/DataSourceModule.kt new file mode 100644 index 000000000..06707e34e --- /dev/null +++ b/network/src/main/java/team/aliens/dms/android/network/outing/di/DataSourceModule.kt @@ -0,0 +1,18 @@ +package team.aliens.dms.android.network.outing.di + +import dagger.Binds +import dagger.Module +import dagger.hilt.InstallIn +import dagger.hilt.components.SingletonComponent +import team.aliens.dms.android.network.outing.datasource.OutingNetworkDataSource +import team.aliens.dms.android.network.outing.datasource.OutingNetworkDataSourceImpl +import javax.inject.Singleton + +@InstallIn(SingletonComponent::class) +@Module +internal abstract class DataSourceModule { + + @Binds + @Singleton + abstract fun bindOutingNetworkDataSource(impl: OutingNetworkDataSourceImpl): OutingNetworkDataSource +} From 345641321ecc7c7b8e97dca0d558ba4581f3a636 Mon Sep 17 00:00:00 2001 From: chlgkdms Date: Thu, 14 Mar 2024 22:14:07 +0900 Subject: [PATCH 017/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20reset=20passw?= =?UTF-8?q?ord=20nav?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/team/aliens/dms/android/app/DmsApp.kt | 9 +++++++++ .../aliens/dms/android/app/navigation/DmsNavigator.kt | 4 ++-- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt b/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt index d90ac627e..c30fbe061 100644 --- a/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt +++ b/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt @@ -31,6 +31,8 @@ import team.aliens.dms.android.app.navigation.unauthorized.UnauthorizedNavGraph import team.aliens.dms.android.feature.destinations.TermsScreenDestination import team.aliens.dms.android.feature.editpassword.EditPasswordViewModel import team.aliens.dms.android.feature.editpassword.navigation.EditPasswordNavGraph +import team.aliens.dms.android.feature.resetpassword.ResetPasswordViewModel +import team.aliens.dms.android.feature.resetpassword.navigation.ResetPasswordNavGraph import team.aliens.dms.android.feature.signup.SignUpViewModel import team.aliens.dms.android.feature.signup.TermsUrl import team.aliens.dms.android.feature.signup.navigation.SignUpNavGraph @@ -70,6 +72,13 @@ fun DmsApp( } hiltViewModel(parentEntry) } + + dependency(ResetPasswordNavGraph) { + val parentEntry = remember(navBackStackEntry) { + navController.getBackStackEntry(ResetPasswordNavGraph.route) + } + hiltViewModel(parentEntry) + } }, ) } diff --git a/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt b/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt index 31ab6655f..64029a1bd 100644 --- a/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt +++ b/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt @@ -104,11 +104,11 @@ class DmsNavigator( } override fun openResetPasswordEnterEmailVerificationCode() { - navController.navigateSingleTop(ResetPasswordEnterEmailVerificationCodeScreenDestination within navGraph) + navController.navigateSingleTop(ResetPasswordEnterEmailVerificationCodeScreenDestination within ResetPasswordNavGraph) } override fun openResetPasswordSetPassword() { - navController.navigateSingleTop(ResetPasswordSetPasswordScreenDestination within navGraph) + navController.navigateSingleTop(ResetPasswordSetPasswordScreenDestination within ResetPasswordNavGraph) } override fun openAuthorizedNav() { From a4e91451c9b8b7b0b9346802bffdbe5ecb898460 Mon Sep 17 00:00:00 2001 From: chlgkdms Date: Thu, 14 Mar 2024 22:14:39 +0900 Subject: [PATCH 018/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20response=20un?= =?UTF-8?q?it?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/network/student/apiservice/StudentApiService.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/network/src/main/java/team/aliens/dms/android/network/student/apiservice/StudentApiService.kt b/network/src/main/java/team/aliens/dms/android/network/student/apiservice/StudentApiService.kt index feadee987..7b0920dee 100644 --- a/network/src/main/java/team/aliens/dms/android/network/student/apiservice/StudentApiService.kt +++ b/network/src/main/java/team/aliens/dms/android/network/student/apiservice/StudentApiService.kt @@ -1,5 +1,6 @@ package team.aliens.dms.android.network.student.apiservice +import retrofit2.Response import retrofit2.http.Body import retrofit2.http.DELETE import retrofit2.http.GET @@ -40,7 +41,7 @@ internal interface StudentApiService { ): FindIdResponse @PATCH("/students/password/initialization") - suspend fun resetPassword(@Body request: ResetPasswordRequest) + suspend fun resetPassword(@Body request: ResetPasswordRequest): Response? @GET("/students/account-id/duplication") suspend fun checkIdDuplication(@Query("account_id") accountId: String) From 0d9d0d5e7f8ec133de0bdb91bfc9ff352d7a3235 Mon Sep 17 00:00:00 2001 From: chlgkdms Date: Thu, 14 Mar 2024 22:15:07 +0900 Subject: [PATCH 019/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20ResetPassword?= =?UTF-8?q?EnterEmailVerificationCode=20Screen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../2_EnterEmailVerificationCodeScreen.kt | 15 -- ...asswordEnterEmailVerificationCodeScreen.kt | 212 ++++++++++++++++++ 2 files changed, 212 insertions(+), 15 deletions(-) delete mode 100644 feature/src/main/java/team/aliens/dms/android/feature/resetpassword/2_EnterEmailVerificationCodeScreen.kt create mode 100644 feature/src/main/java/team/aliens/dms/android/feature/resetpassword/2_ResetPasswordEnterEmailVerificationCodeScreen.kt diff --git a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/2_EnterEmailVerificationCodeScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/2_EnterEmailVerificationCodeScreen.kt deleted file mode 100644 index 91340f018..000000000 --- a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/2_EnterEmailVerificationCodeScreen.kt +++ /dev/null @@ -1,15 +0,0 @@ -package team.aliens.dms.android.feature.resetpassword - -import androidx.compose.runtime.Composable -import androidx.compose.ui.Modifier -import com.ramcosta.composedestinations.annotation.Destination -import team.aliens.dms.android.feature.resetpassword.navigation.ResetPasswordNavigator - -@Destination -@Composable -internal fun ResetPasswordEnterEmailVerificationCodeScreen( - modifier: Modifier = Modifier, - navigator: ResetPasswordNavigator, -) { - -} diff --git a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/2_ResetPasswordEnterEmailVerificationCodeScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/2_ResetPasswordEnterEmailVerificationCodeScreen.kt new file mode 100644 index 000000000..2c5807f4c --- /dev/null +++ b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/2_ResetPasswordEnterEmailVerificationCodeScreen.kt @@ -0,0 +1,212 @@ +package team.aliens.dms.android.feature.resetpassword + +import android.os.CountDownTimer +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text +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 +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.style.TextAlign +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import com.ramcosta.composedestinations.annotation.Destination +import team.aliens.dms.android.core.designsystem.ButtonDefaults +import team.aliens.dms.android.core.designsystem.ContainedButton +import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.DmsTheme +import team.aliens.dms.android.core.designsystem.DmsTopAppBar +import team.aliens.dms.android.core.designsystem.LocalToast +import team.aliens.dms.android.core.designsystem.TextButton +import team.aliens.dms.android.core.designsystem.VerificationCodeInput +import team.aliens.dms.android.core.designsystem.VerificationCodeInputDefaults +import team.aliens.dms.android.core.ui.Banner +import team.aliens.dms.android.core.ui.BannerDefaults +import team.aliens.dms.android.core.ui.DefaultVerticalSpace +import team.aliens.dms.android.core.ui.bottomPadding +import team.aliens.dms.android.core.ui.collectInLaunchedEffectWithLifecycle +import team.aliens.dms.android.core.ui.horizontalPadding +import team.aliens.dms.android.core.ui.startPadding +import team.aliens.dms.android.core.ui.topPadding +import team.aliens.dms.android.feature.R +import team.aliens.dms.android.feature.resetpassword.navigation.ResetPasswordNavigator + +// Millisecond * Second * Minutes +private const val TIMER_TOTAL_SECONDS: Long = 1000 * 60 * 3 +private const val TIMER_INTERVAL: Long = 1000 + +@OptIn(ExperimentalMaterial3Api::class) +@Destination +@Composable +internal fun ResetPasswordEnterEmailVerificationCodeScreen( + modifier: Modifier = Modifier, + navigator: ResetPasswordNavigator, + viewModel: ResetPasswordViewModel, +) { + val uiState by viewModel.stateFlow.collectAsStateWithLifecycle() + val toast = LocalToast.current + val context = LocalContext.current + var timerText: String by remember { mutableStateOf("") } + + var isVerificationInputAvailable by remember { mutableStateOf(true) } + var isSessionExpired by remember { mutableStateOf(false) } + + val timer: CountDownTimer = remember { + object : CountDownTimer(TIMER_TOTAL_SECONDS, TIMER_INTERVAL) { + override fun onTick(millisUntilFinished: Long) { + val minutes = millisUntilFinished / (1000 * 60) + val seconds = millisUntilFinished / 1000 % 60 + timerText = context.getString(R.string.format_timer_m_s, minutes, seconds) + } + + override fun onFinish() { + isVerificationInputAvailable = false + isSessionExpired = true + viewModel.postIntent(ResetPasswordIntent.UpdateEmailVerificationCode(value = "")) + } + } + } + + LaunchedEffect(uiState.sessionId) { + timer.start() + } + + viewModel.sideEffectFlow.collectInLaunchedEffectWithLifecycle { sideEffect -> + when (sideEffect) { + ResetPasswordSideEffect.EmailVerificationCodeChecked -> { + timer.cancel() + navigator.openResetPasswordSetPassword() + } + + ResetPasswordSideEffect.EmailVerificationCodeIncorrect -> toast.showErrorToast( + message = context.getString(R.string.sign_up_enter_email_verification_code_error_verification_code_incorrect), + ) + + ResetPasswordSideEffect.EmailVerificationSessionReset -> { + isVerificationInputAvailable = true + with(timer) { + cancel() + start() + } + toast.showSuccessToast( + message = context.getString(R.string.sign_up_enter_email_verification_code_success_resent_email), + ) + } + + ResetPasswordSideEffect.EmailVerificationSessionResetFailed -> toast.showErrorToast( + message = context.getString(R.string.sign_up_enter_email_verification_code_error_cannot_resend_verification_code), + ) + + else -> {//* explicit blank *//* + } + } + } + + DmsScaffold( + modifier = modifier, + topBar = { + DmsTopAppBar( + title = {}, + navigationIcon = { + IconButton(onClick = navigator::openSignIn) { + Icon( + painter = painterResource(id = R.drawable.ic_baseline_arrow_back_24), + contentDescription = stringResource(id = R.string.top_bar_back_button), + ) + } + }, + ) + }, + ) { padValues -> + Column( + modifier = Modifier + .fillMaxSize() + .padding(padValues) + .imePadding(), + ) { + Banner( + modifier = Modifier + .fillMaxWidth() + .topPadding(BannerDefaults.DefaultTopSpace) + .startPadding(), + message = { + BannerDefaults.DefaultText(text = stringResource(id = R.string.sign_up_enter_email_verification_code)) + }, + ) + Spacer(modifier = Modifier.weight(1f)) + VerificationCodeInput( + modifier = Modifier + .fillMaxWidth() + .horizontalPadding(), + totalLength = ResetPasswordViewModel.EMAIL_VERIFICATION_CODE_LENGTH, + text = uiState.emailVerificationCode, + onValueChange = { verificationCode -> + viewModel.postIntent(ResetPasswordIntent.UpdateEmailVerificationCode(value = verificationCode)) + }, + supportingText = { + VerificationCodeInputDefaults.SupportingText( + text = stringResource(id = R.string.sign_up_enter_email_verification_code_please_enter_6_digit_code_sent_to_email), + ) + }, + enabled = isVerificationInputAvailable, + ) + Spacer(modifier = Modifier.height(DefaultVerticalSpace)) + Text( + modifier = Modifier.fillMaxWidth(), + textAlign = TextAlign.Center, + text = if (isVerificationInputAvailable) { + timerText + } else { + stringResource( + id = if (isSessionExpired) { + R.string.sign_up_enter_email_verification_code_error_timeout + } else { + R.string.sign_up_enter_email_verification_code_error_verification_code_incorrect + }, + ) + }, + style = DmsTheme.typography.caption, + color = if (isVerificationInputAvailable) { + DmsTheme.colorScheme.primary + } else { + DmsTheme.colorScheme.error + }, + ) + Spacer(modifier = Modifier.weight(3f)) + TextButton( + modifier = Modifier + .fillMaxWidth() + .horizontalPadding(), + onClick = { viewModel.postIntent(ResetPasswordIntent.ResetEmailVerificationSession) }, + colors = ButtonDefaults.textGrayButtonColors(), + ) { + Text(text = stringResource(id = R.string.sign_up_enter_email_verification_code_resend_verification_code)) + } + Spacer(modifier = Modifier.height(DefaultVerticalSpace)) + ContainedButton( + modifier = Modifier + .fillMaxWidth() + .horizontalPadding() + .bottomPadding(), + onClick = { viewModel.postIntent(ResetPasswordIntent.CheckEmailVerificationCode) }, + enabled = uiState.emailVerificationCode.length == ResetPasswordViewModel.EMAIL_VERIFICATION_CODE_LENGTH, + ) { + Text(text = stringResource(id = R.string.verify)) + } + } + } +} From 1c05ca8e28b8f7932b2888f953e1d45c9bca7ff4 Mon Sep 17 00:00:00 2001 From: chlgkdms Date: Thu, 14 Mar 2024 22:15:25 +0900 Subject: [PATCH 020/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20AccountVerifi?= =?UTF-8?q?cationScreen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../1_AccountVerificationScreen.kt | 378 +++++++++--------- 1 file changed, 193 insertions(+), 185 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/1_AccountVerificationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/1_AccountVerificationScreen.kt index 7a27c801b..0d4f8b533 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/1_AccountVerificationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/1_AccountVerificationScreen.kt @@ -1,228 +1,236 @@ package team.aliens.dms.android.feature.resetpassword +import androidx.activity.compose.BackHandler +import androidx.compose.animation.AnimatedVisibility +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.saveable.rememberSaveable +import androidx.compose.runtime.setValue import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination +import kotlinx.coroutines.delay +import team.aliens.dms.android.core.designsystem.ContainedButton +import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.DmsTheme +import team.aliens.dms.android.core.designsystem.DmsTopAppBar +import team.aliens.dms.android.core.designsystem.LocalToast +import team.aliens.dms.android.core.designsystem.ShadowDefaults +import team.aliens.dms.android.core.designsystem.TextField +import team.aliens.dms.android.core.ui.Banner +import team.aliens.dms.android.core.ui.BannerDefaults +import team.aliens.dms.android.core.ui.DefaultVerticalSpace +import team.aliens.dms.android.core.ui.bottomPadding +import team.aliens.dms.android.core.ui.collectInLaunchedEffectWithLifecycle +import team.aliens.dms.android.core.ui.horizontalPadding +import team.aliens.dms.android.core.ui.startPadding +import team.aliens.dms.android.core.ui.topPadding +import team.aliens.dms.android.core.ui.verticalPadding +import team.aliens.dms.android.feature.R import team.aliens.dms.android.feature.resetpassword.navigation.ResetPasswordNavigator // TODO Pop backstack +@OptIn(ExperimentalMaterial3Api::class) @Destination @Composable fun AccountVerificationScreen( modifier: Modifier = Modifier, navigator: ResetPasswordNavigator, - // changePasswordViewModel: ChangePasswordViewModel = hiltViewModel(), // fixme - // resetPasswordVerificationViewModel: ResetPasswordVerificationViewModel = hiltViewModel(), // fixme -) {/* - - val focusManager = LocalFocusManager.current - + viewModel: ResetPasswordViewModel, +) { + val uiState by viewModel.stateFlow.collectAsStateWithLifecycle() + val toast = LocalToast.current val context = LocalContext.current + val (idChecked, onChangeIdChecked) = rememberSaveable { mutableStateOf(false) } - val toast = rememberToast() - - val pattern = Patterns.EMAIL_ADDRESS - - var id by remember { mutableStateOf("") } - var name by remember { mutableStateOf("") } - var userEmail by remember { mutableStateOf("") } - - var isIdError by remember { mutableStateOf(false) } - var isNameError by remember { mutableStateOf(false) } - var isEmailError by remember { mutableStateOf(false) } - - val onIdChange = { userId: String -> - if (userId.length != id.length) isIdError = false - id = userId - } - - val onNameChange = { userName: String -> - if (userName.length != name.length) isNameError = false - name = userName - } - - val onEmailChange = { value: String -> - if (value.length != userEmail.length) isEmailError = false - userEmail = value + LaunchedEffect(uiState.accountId) { + if (uiState.accountId.isNotEmpty()) { + delay(300L) + viewModel.postIntent(ResetPasswordIntent.CheckAccountId) + } } - var emailResponse by remember { mutableStateOf("") } + var isAccountIdError by rememberSaveable(uiState.accountId) { mutableStateOf(false) } - LaunchedEffect(Unit) { - changePasswordViewModel.editPasswordEffect.collect { - when (it) { - is ChangePasswordViewModel.Event.CheckIdSuccess -> { - emailResponse = it.email - } - - is ChangePasswordViewModel.Event.NotFoundException -> { - isIdError = true - } - - else -> { - toast( - getStringFromEvent( - context = context, - event = it, - ) - ) - } + viewModel.sideEffectFlow.collectInLaunchedEffectWithLifecycle { sideEffect -> + when (sideEffect) { + ResetPasswordSideEffect.AccountIdExists -> { + onChangeIdChecked(true) } - } - } - LaunchedEffect(Unit) { - resetPasswordVerificationViewModel.registerEmailEvent.collect { - when (it) { - is ResetPasswordVerificationEvent.SendEmailSuccess -> navigator::openResetPasswordEnterEmailVerificationCode - is ResetPasswordVerificationEvent.TooManyRequestsException -> { - toast(context.getString(R.string.Retry)) - } + ResetPasswordSideEffect.AccountIdNotExists -> toast.showErrorToast( + message = context.getString(R.string.reset_password_account_id_does_not_exist), + ) - else -> toast( - getStringFromEmailEvent( - context = context, - event = it, - ) - ) + ResetPasswordSideEffect.SendEmailVerificationCodeSuccess -> navigator.openResetPasswordEnterEmailVerificationCode() + + else -> {/* explicit blank */ } } } - Column( - modifier = modifier - .fillMaxSize() - .background( - DormTheme.colors.surface, - ) - .fillMaxHeight(0.8f) - .padding( - top = 108.dp, - start = 16.dp, - end = 16.dp, + DmsScaffold( + modifier = modifier, + topBar = { + DmsTopAppBar( + title = {}, + navigationIcon = { + IconButton( + onClick = { navigator.openSignIn() }, + ) { + Icon( + painter = painterResource(id = R.drawable.ic_baseline_arrow_back_24), + contentDescription = stringResource(id = R.string.top_bar_back_button), + ) + } + }, ) - .dormClickable( - rippleEnabled = false, - ) { - focusManager.clearFocus() - } - ) { - AppLogo( - darkIcon = isSystemInDarkTheme(), - ) - Space(space = 8.dp) - Body2( - text = stringResource(id = R.string.Identification), - ) + }, + ) { padValues -> Column( modifier = Modifier - .padding(top = 60.dp) + .fillMaxSize() + .padding(padValues) + .imePadding(), + verticalArrangement = Arrangement.spacedBy(DefaultVerticalSpace), ) { - Box( - modifier = Modifier.height(68.dp), - ) { - DormTextField( - value = id, - onValueChange = onIdChange, - hint = stringResource(id = R.string.EnterId), - error = isIdError, - errorDescription = stringResource(id = R.string.NotExistId), - keyboardActions = KeyboardActions { - if (id.isNotBlank()) { - changePasswordViewModel.checkId( - accountId = id, - ) - focusManager.clearFocus() - } - }, - imeAction = ImeAction.Done, - ) - } + Banner( + modifier = Modifier + .fillMaxWidth() + .topPadding(BannerDefaults.DefaultTopSpace) + .startPadding(), + message = { + BannerDefaults.DefaultText(text = stringResource(id = R.string.reset_password_identification_verification)) + }, + ) + Spacer(modifier = Modifier.weight(1f)) + TextField( + modifier = Modifier + .fillMaxWidth() + .horizontalPadding(), + value = uiState.accountId, + hint = { + Text(text = stringResource(id = R.string.reset_password_enter_account_id)) + }, + onValueChange = { viewModel.postIntent(ResetPasswordIntent.UpdateAccountId(value = it)) }, + supportingText = if (isAccountIdError) { + { Text(text = stringResource(id = R.string.reset_password_enter_account_id_error_invalid_format)) } + } else { + null + }, + isError = isAccountIdError, + ) AnimatedVisibility( - visible = emailResponse.isNotBlank() + modifier = Modifier.fillMaxWidth(), + visible = idChecked, ) { Column( - modifier = Modifier + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(DefaultVerticalSpace), ) { - Column( + AccountAssertionCard( modifier = Modifier - .fillMaxWidth() - .background( - DormTheme.colors.background, - ) - .padding( - horizontal = 16.dp, - vertical = 12.dp, - ) - ) { - Body2( - text = stringResource(id = R.string.MatchEmailToId), - ) - Body2( - modifier = Modifier.padding( - top = 8.dp, - ), - text = emailResponse, - color = DormTheme.colors.primary, - ) - } - Box( + .horizontalPadding() + .verticalPadding() + .fillMaxWidth(), + hashedEmail = uiState.hashedEmail, + ) + TextField( modifier = Modifier - .height(68.dp) - .padding(top = 24.dp) - ) { - DormTextField( - value = name, - onValueChange = onNameChange, - hint = stringResource(id = R.string.EnterName), - imeAction = ImeAction.Next, - ) - } - Space(space = 32.dp) - Box( + .fillMaxWidth() + .horizontalPadding(), + value = uiState.studentName, + hint = { + Text(text = stringResource(id = R.string.reset_password_enter_student_name)) + }, + onValueChange = { + viewModel.postIntent(ResetPasswordIntent.UpdateStudentName(value = it)) + }, + ) + TextField( modifier = Modifier - .height(68.dp) - ) { - DormTextField( - value = userEmail, - onValueChange = onEmailChange, - hint = stringResource(id = R.string.EnterEmailAddress), - error = isEmailError, - keyboardType = KeyboardType.Email, - errorDescription = context.getString(R.string.NotValidEmailFormat), - keyboardActions = KeyboardActions { - focusManager.clearFocus() - }, - imeAction = ImeAction.Done, - ) - } + .fillMaxWidth() + .horizontalPadding(), + value = uiState.email, + hint = { + Text(text = stringResource(id = R.string.reset_password_enter_email)) + }, + onValueChange = { + viewModel.postIntent(ResetPasswordIntent.UpdateEmail(value = it)) + }, + ) } - } - - RatioSpace(height = if (emailResponse.isEmpty()) 0.05f else 0.622f) - DormContainedLargeButton( - text = stringResource(id = R.string.Next), - color = DormButtonColor.Blue, - enabled = if (emailResponse.isEmpty()) id.isNotBlank() && !isIdError - else (id.isNotBlank() && name.isNotBlank() && userEmail.isNotBlank()) - ) { - if (id.isNotBlank() && name.isNotBlank() && userEmail.isNotBlank()) { - if (pattern.matcher(userEmail).find()) { - resetPasswordVerificationViewModel.requestEmailCode( - email = userEmail.trim(), - type = EmailVerificationType.PASSWORD, + } + Spacer(modifier = Modifier.weight(3f)) + ContainedButton( + modifier = Modifier + .fillMaxWidth() + .horizontalPadding() + .bottomPadding(), + onClick = { + viewModel.postIntent( + ResetPasswordIntent.SendEmailVerificationCode( + uiState.email ) - } else { - isEmailError = true - } - } else { - changePasswordViewModel.checkId( - accountId = id.trim(), ) - focusManager.clearFocus() - } + }, + enabled = uiState.accountId.isNotEmpty() && uiState.studentName.isNotEmpty() && uiState.email.isNotEmpty(), + ) { + Text(text = stringResource(id = R.string.next)) } } - }*/ + } + BackHandler { + navigator.openSignIn() + } } + +@Composable +private fun AccountAssertionCard( + modifier: Modifier = Modifier, + hashedEmail: String, +) { + Card( + modifier = modifier, + shape = DmsTheme.shapes.surfaceSmall, + colors = CardDefaults.cardColors( + containerColor = DmsTheme.colorScheme.surface, + contentColor = DmsTheme.colorScheme.onSurface, + ), + elevation = CardDefaults.outlinedCardElevation(defaultElevation = ShadowDefaults.SmallElevation), + ) { + Column( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(DefaultVerticalSpace), + ) { + Text( + modifier = Modifier.startPadding(), + text = stringResource(id = R.string.reset_password_account_id_match_email), + ) + Text( + modifier = Modifier.startPadding(), + text = hashedEmail, + color = DmsTheme.colorScheme.primary, + ) + } + } +} \ No newline at end of file From 1a3934507772d987717b773a8a881b7dee31052e Mon Sep 17 00:00:00 2001 From: chlgkdms Date: Thu, 14 Mar 2024 22:15:37 +0900 Subject: [PATCH 021/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20SetPasswordSc?= =?UTF-8?q?reen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resetpassword/3_SetPasswordScreen.kt | 290 ++++++++---------- 1 file changed, 129 insertions(+), 161 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/3_SetPasswordScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/3_SetPasswordScreen.kt index c8a2ee8bc..43b45b6ba 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/3_SetPasswordScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/3_SetPasswordScreen.kt @@ -1,205 +1,173 @@ package team.aliens.dms.android.feature.resetpassword +import androidx.activity.compose.BackHandler +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.padding +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination +import team.aliens.dms.android.core.designsystem.AlertDialog +import team.aliens.dms.android.core.designsystem.ContainedButton +import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.DmsTopAppBar +import team.aliens.dms.android.core.designsystem.LocalToast +import team.aliens.dms.android.core.designsystem.TextButton +import team.aliens.dms.android.core.ui.Banner +import team.aliens.dms.android.core.ui.BannerDefaults +import team.aliens.dms.android.core.ui.DefaultVerticalSpace +import team.aliens.dms.android.core.ui.bottomPadding +import team.aliens.dms.android.core.ui.collectInLaunchedEffectWithLifecycle +import team.aliens.dms.android.core.ui.composable.PasswordTextField +import team.aliens.dms.android.core.ui.horizontalPadding +import team.aliens.dms.android.core.ui.startPadding +import team.aliens.dms.android.core.ui.topPadding +import team.aliens.dms.android.feature.R import team.aliens.dms.android.feature.resetpassword.navigation.ResetPasswordNavigator +import team.aliens.dms.android.feature.signup.SignUpIntent +import team.aliens.dms.android.feature.signup.SignUpSideEffect @Suppress("ConstPropertyName") private const val passwordFormat = "^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[!@#$%^&*()_+=-]).{8,20}" +@OptIn(ExperimentalMaterial3Api::class) @Destination @Composable fun ResetPasswordSetPasswordScreen( modifier: Modifier = Modifier, navigator: ResetPasswordNavigator, - // changePasswordViewModel: ChangePasswordViewModel = hiltViewModel(), -) {/* + viewModel: ResetPasswordViewModel, +) { + val uiState by viewModel.stateFlow.collectAsStateWithLifecycle() - val context = LocalContext.current - - val toast = rememberToast() - - val focusManager = LocalFocusManager.current - - var password by remember { mutableStateOf("") } - var repeatPassword by remember { mutableStateOf("") } + val (showPassword, onShowPasswordChange) = remember { mutableStateOf(false) } + val (showPasswordRepeat, onShowPasswordRepeatChange) = remember { mutableStateOf(false) } - var isPasswordFormatError by remember { mutableStateOf(false) } - var isPasswordMatchError by remember { mutableStateOf(false) } - - var isShowDialog by remember { mutableStateOf(false) } - var isPressedBackButton by remember { mutableStateOf(false) } + val toast = LocalToast.current + val context = LocalContext.current - val onPasswordChange = { passwordValue: String -> - if (passwordValue.length != password.length) isPasswordFormatError = false - password = passwordValue + val (shouldShowQuitSignUpDialog, onShouldShowQuitSignUpDialogChange) = remember { + mutableStateOf(false) } - val onRepeatPasswordChange = { repeatPasswordValue: String -> - if (repeatPasswordValue.length != repeatPassword.length) isPasswordMatchError = false - repeatPassword = repeatPasswordValue + if (shouldShowQuitSignUpDialog) { + AlertDialog( + text = { Text(text = stringResource(id = R.string.reset_password_password_changed)) }, + onDismissRequest = { /* explicit blank */ }, + confirmButton = { + TextButton( + onClick = navigator::openSignIn, + ) { + Text(text = stringResource(id = R.string.reset_password_go_sign_in_screen)) + } + }, + ) } - BackHandler(enabled = true) { - isPressedBackButton = true - } - Column( - modifier = modifier - .fillMaxSize() - .background( - color = DormTheme.colors.surface, + viewModel.sideEffectFlow.collectInLaunchedEffectWithLifecycle { sideEffect -> + when (sideEffect) { + ResetPasswordSideEffect.PasswordReset -> onShouldShowQuitSignUpDialogChange(true) + ResetPasswordSideEffect.PasswordMismatch -> toast.showErrorToast( + message = context.getString(R.string.sign_up_set_password_error_password_mismatch), ) - .dormClickable( - rippleEnabled = false, - ) { - focusManager.clearFocus() - }, - ) { - TopBar( - title = stringResource(R.string.ChangePassword), - onPrevious = navigator::popBackStack, - ) - - if (isShowDialog) { - DormCustomDialog( - onDismissRequest = {}, - ) { - DormSingleButtonDialog( - content = stringResource(id = R.string.SuccessChangePassword), - mainBtnText = stringResource(id = R.string.GoLogin), - onMainBtnClick = navigator::openSignIn, - mainBtnTextColor = DormColor.DormPrimary, + ResetPasswordSideEffect.InvalidPassword -> { + toast.showErrorToast( + message = context.getString(R.string.sign_up_set_password_invalid_password), ) } - Image( - modifier = Modifier - .padding(top = 32.dp, bottom = 7.dp) - .height(85.dp) - .width(85.dp), - painter = painterResource(team.aliens.dms.android.designsystem.R.drawable.ic_information), - contentDescription = stringResource(id = R.string.MainLogo), - ) - - Space(space = 1.dp) - - Body4( - text = stringResource(id = R.string.SetNewPassword), - ) - } - - if (isPressedBackButton) { - DormCustomDialog( - onDismissRequest = { *//*TODO*//* }, - ) { - DormDoubleButtonDialog( - content = stringResource(id = R.string.FinishResetPassword), - mainBtnText = stringResource(id = R.string.Yes), - subBtnText = stringResource(id = R.string.No), - onMainBtnClick = navigator::openSignIn, - onSubBtnClick = { isPressedBackButton = false }, - ) + else -> {/* explicit blank */ } } + } - LaunchedEffect(Unit) { - changePasswordViewModel.editPasswordEffect.collect { - when (it) { - is ChangePasswordViewModel.Event.ResetPasswordSuccess -> { - toast(context.getString(R.string.SuccessResetPassword)) - navigator.openSignIn() - } - - else -> { - toast( - getStringFromEvent( - context = context, - event = it, - ) + DmsScaffold( + modifier = modifier, + topBar = { + DmsTopAppBar( + title = {}, + navigationIcon = { + IconButton(onClick = { navigator.openSignIn() }) { + Icon( + painter = painterResource(id = R.drawable.ic_baseline_arrow_back_24), + contentDescription = stringResource(id = R.string.top_bar_back_button), ) } - } - } - } - + }, + ) + }, + ) { padValues -> Column( modifier = Modifier .fillMaxSize() - .padding( - top = 38.dp, - start = 16.dp, - end = 16.dp, - ) + .padding(padValues) + .imePadding(), ) { - AppLogo() - Space(space = 8.dp) - Body2( - text = stringResource(id = R.string.ChangePassword), - ) - Space(space = 4.dp) - Caption( - text = stringResource(id = R.string.PasswordWarning), - color = DormColor.Gray500, - ) - Column( + Spacer(modifier = Modifier.weight(1f)) + Banner( modifier = Modifier .fillMaxWidth() - .padding(top = 40.dp), + .topPadding(BannerDefaults.DefaultTopSpace) + .startPadding(), + message = { BannerDefaults.DefaultText(text = stringResource(id = R.string.edit_password_new_password)) }, + ) + Spacer(modifier = Modifier.weight(1f)) + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(DefaultVerticalSpace), ) { - Box(modifier = Modifier.height(76.dp)) { - DormTextField( - value = password, - onValueChange = onPasswordChange, - error = isPasswordFormatError, - isPassword = true, - hint = stringResource(id = R.string.ScanNewPassword), - errorDescription = stringResource(id = R.string.CheckPasswordFormat), - imeAction = ImeAction.Next, - ) - } - Space(space = 7.dp) - Box( - modifier = Modifier.height(76.dp), - ) { - DormTextField( - value = repeatPassword, - onValueChange = onRepeatPasswordChange, - error = isPasswordMatchError, - isPassword = true, - hint = stringResource(id = R.string.CheckScanNewPassword), - errorDescription = stringResource(id = R.string.MismatchRepeatPassword), - keyboardActions = KeyboardActions { - focusManager.clearFocus() - }, - imeAction = ImeAction.Done, - ) - } + PasswordTextField( + modifier = Modifier + .fillMaxWidth() + .horizontalPadding(), + value = uiState.newPassword, + onValueChange = { viewModel.postIntent(ResetPasswordIntent.UpdateNewPassword(value = it)) }, + passwordShowing = showPassword, + onPasswordShowingChange = onShowPasswordChange, + hintText = stringResource(id = R.string.edit_password_please_enter_new_password) + ) + PasswordTextField( + modifier = Modifier + .fillMaxWidth() + .horizontalPadding(), + value = uiState.newPasswordRepeat, + onValueChange = { viewModel.postIntent(ResetPasswordIntent.UpdateNewPasswordRepeat(value = it)) }, + passwordShowing = showPasswordRepeat, + onPasswordShowingChange = onShowPasswordRepeatChange, + hintText = stringResource(id = R.string.edit_password_please_enter_new_password_repeat) + ) } - RatioSpace(height = 0.742f) - DormContainedLargeButton( - text = stringResource(id = R.string.Check), - color = DormButtonColor.Blue, - enabled = (password.isNotBlank() && repeatPassword.isNotBlank()) + Spacer(modifier = Modifier.weight(3f)) + ContainedButton( + modifier = Modifier + .fillMaxWidth() + .horizontalPadding() + .bottomPadding(), + onClick = { viewModel.postIntent(ResetPasswordIntent.SetPassword) }, + enabled = uiState.newPassword.isNotEmpty() && uiState.newPasswordRepeat.isNotEmpty(), ) { - if (password != repeatPassword) { - isPasswordMatchError = true - } else if (!Pattern.compile(passwordFormat).matcher(password).find()) { - isPasswordFormatError = true - } else { - *//* todo - navController.previousBackStackEntry?.arguments?.run { - changePasswordViewModel.resetPassword( - accountId = getString("accountId").toString(), - emailVerificationCode = getString("authCode").toString(), - email = getString("email").toString(), - studentName = getString("name").toString(), - newPassword = password, - ) - }*//* - } + Text(text = stringResource(id = R.string.next)) } } - }*/ + } + BackHandler { + onShouldShowQuitSignUpDialogChange(true) + } } From ad06c5e26d704c9ec82c26f8f3e50ce5569f7805 Mon Sep 17 00:00:00 2001 From: chlgkdms Date: Thu, 14 Mar 2024 22:15:49 +0900 Subject: [PATCH 022/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20reset=20passw?= =?UTF-8?q?ord=20vm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resetpassword/ResetPasswordViewModel.kt | 480 +++++++----------- 1 file changed, 184 insertions(+), 296 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/ResetPasswordViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/ResetPasswordViewModel.kt index 4ee0478c5..fcb563e28 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/ResetPasswordViewModel.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/ResetPasswordViewModel.kt @@ -1,338 +1,226 @@ package team.aliens.dms.android.feature.resetpassword -/* -import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import team.aliens.dms.android.domain.model._common.EmailVerificationType -import team.aliens.dms.android.domain.model.auth.CheckEmailVerificationCodeInput -import team.aliens.dms.android.feature._legacy.base.BaseViewModel1 -import team.aliens.dms.android.feature._legacy.util.MutableEventFlow -import team.aliens.dms.android.feature._legacy.util.asEventFlow -import team.aliens.dms.android.domain.model.auth.CheckIdExistsInput -import team.aliens.dms.android.domain.model.auth.SendEmailVerificationCodeInput -import team.aliens.dms.android.domain.model.student.CheckEmailDuplicationInput -import team.aliens.dms.android.domain.model.student.ResetPasswordInput -import team.aliens.dms.android.domain.model.user.ComparePasswordInput -import team.aliens.dms.android.domain.model.user.EditPasswordInput -import team.aliens.dms.android.domain.usecase.auth.CheckEmailVerificationCodeUseCase -import team.aliens.dms.android.domain.usecase.auth.CheckIdExistsUseCase -import team.aliens.dms.android.domain.usecase.auth.SendEmailVerificationCodeUseCase -import team.aliens.dms.android.domain.usecase.student.CheckEmailDuplicationUseCase -import team.aliens.dms.android.domain.usecase.student.ResetPasswordUseCase -import team.aliens.dms.android.domain.usecase.user.ComparePasswordUseCase -import team.aliens.dms.android.domain.usecase.user.EditPasswordUseCase -import team.aliens.dms.android.feature._legacy.base.MviEvent -import team.aliens.dms.android.feature._legacy.base._MviState +import team.aliens.dms.android.core.ui.mvi.BaseMviViewModel +import team.aliens.dms.android.core.ui.mvi.Intent +import team.aliens.dms.android.core.ui.mvi.SideEffect +import team.aliens.dms.android.core.ui.mvi.UiState +import team.aliens.dms.android.data.auth.model.EmailVerificationType +import team.aliens.dms.android.data.auth.repository.AuthRepository +import team.aliens.dms.android.data.student.repository.StudentRepository +import team.aliens.dms.android.shared.validator.checkIfPasswordValid +import java.util.UUID import javax.inject.Inject @HiltViewModel -class ChangePasswordViewModel @Inject constructor( - private val changePasswordUseCase: ResetPasswordUseCase, - private val editPasswordUseCase: EditPasswordUseCase, - private val comparePasswordUseCase: ComparePasswordUseCase, - private val checkIdUseCase: CheckIdExistsUseCase, -) : BaseViewModel1() { - - */ -/* - 디자인에서 처음 본인인증할때 아이디만을 사용해서 "아이디 존재 여부(비밀번호 재설정)"이라는 Api로 이에 해당하는 Email를 받습니다. - 그다음 아이디를 입력 받은 다음에 "이메일 검증이라는 Api를 사용하여 이메일과 아이디를 서버에 보낸뒤 이 값들이 정보와 일치하는지 검사합니다." - 검사에서 가능이 뜨게 된다면 "이메일 인증번호 보내기 APi"를 사용해서 사용자 이메일에 이메일을 발송합니다. - 그리고 이메일 인증번호 확인 Api를 사용하여 인증을 완료하고 Students의 비밀번호 재설정 Api를 사용하여 재설정합니다. - *//* - - - override val initialState: ChangePasswordState - get() = ChangePasswordState.getDefaultInstance() - - private val _editPasswordEffect = MutableEventFlow() - var editPasswordEffect = _editPasswordEffect.asEventFlow() - - internal fun editPassword() { - viewModelScope.launch { - kotlin.runCatching { - with(state.value) { - if (newPassword == repeatPassword) { - editPasswordUseCase( - editPasswordInput = EditPasswordInput( - currentPassword = currentPassword, - newPassword = newPassword, - ) - ) - } - } - }.onSuccess { - event(Event.EditPasswordSuccess) - }.onFailure { - event(getEventFromThrowableChangePassword(it)) - } +class ResetPasswordViewModel @Inject constructor( + private val studentRepository: StudentRepository, + private val authRepository: AuthRepository, +) : BaseMviViewModel( + initialState = ResetPasswordUiState.initial() +) { + /*디자인에서 처음 본인인증할때 아이디만을 사용해서 "아이디 존재 여부(비밀번호 재설정)"이라는 Api로 이에 해당하는 Email를 받습니다. + 그다음 아이디를 입력 받은 다음에 "이메일 검증이라는 Api를 사용하여 이메일과 아이디를 서버에 보낸뒤 이 값들이 정보와 일치하는지 검사합니다." + 검사에서 가능이 뜨게 된다면 "이메일 인증번호 보내기 APi"를 사용해서 사용자 이메일에 이메일을 발송합니다. + 그리고 이메일 인증번호 확인 Api를 사용하여 인증을 완료하고 Students의 비밀번호 재설정 Api를 사용하여 재설정합니다.*/ + + override fun processIntent(intent: ResetPasswordIntent) { + when (intent) { + ResetPasswordIntent.SetPassword -> resetPassword() + is ResetPasswordIntent.UpdateNewPassword -> this.updateNewPassword(value = intent.value) + is ResetPasswordIntent.UpdateEmailVerificationCode -> updateEmailVerificationCode(value = intent.value) + ResetPasswordIntent.CheckEmailVerificationCode -> checkEmailVerificationCode() + ResetPasswordIntent.ResetEmailVerificationSession -> resetEmailVerificationSession() + is ResetPasswordIntent.UpdateAccountId -> this.updateAccountId(value = intent.value) + is ResetPasswordIntent.CheckAccountId -> checkIdExists() + is ResetPasswordIntent.UpdateStudentName -> this.updateStudentName(value = intent.value) + is ResetPasswordIntent.UpdateEmail -> this.updateEmail(value = intent.value) + is ResetPasswordIntent.SendEmailVerificationCode -> this.sendEmailVerificationCode(email = intent.value) + is ResetPasswordIntent.UpdateNewPasswordRepeat -> updateNewPasswordRepeat(value = intent.value) } } - internal fun comparePassword() { - viewModelScope.launch { - kotlin.runCatching { - comparePasswordUseCase( - comparePasswordInput = ComparePasswordInput( - password = state.value.currentPassword, - ), - ) - }.onSuccess { - event(Event.ComparePasswordSuccess) - }.onFailure { - event(getEventFromThrowableChangePassword(it)) - } - } - } - internal fun checkId( - accountId: String, - ) { - viewModelScope.launch { - kotlin.runCatching { - checkIdUseCase( - checkIdExistsInput = CheckIdExistsInput( - accountId = accountId, - ), - ) - }.onSuccess { - event(Event.CheckIdSuccess(it.email)) - }.onFailure { - event(getEventFromThrowableChangePassword(it)) - } + private fun resetPassword() = viewModelScope.launch(Dispatchers.IO) { + val capturedState = stateFlow.value + if (capturedState.newPassword != capturedState.newPasswordRepeat) { + postSideEffect(ResetPasswordSideEffect.PasswordMismatch) + return@launch } - } - internal fun resetPassword( - accountId: String, - email: String, - emailVerificationCode: String, - studentName: String, - newPassword: String, - ) { - viewModelScope.launch { - kotlin.runCatching { - state.value.run { - changePasswordUseCase( - resetPasswordInput = ResetPasswordInput( - accountId = accountId, - studentName = studentName, - email = email, - emailVerificationCode = emailVerificationCode, - newPassword = newPassword, - ), - ) - } - }.onSuccess { - event(Event.ResetPasswordSuccess) - }.onFailure { - event(getEventFromThrowableChangePassword(it)) - } + if (!checkIfPasswordValid(capturedState.newPassword)) { + postSideEffect(ResetPasswordSideEffect.PasswordFormatError) + return@launch } - } - internal fun setCurrentPassword( - currentPassword: String, - ) { - sendEvent(event = ChangePasswordEvent.SetCurrentPassword(currentPassword)) + runCatching { + studentRepository.resetPassword( + accountId = capturedState.accountId, + studentName = capturedState.studentName, + email = capturedState.email, + emailVerificationCode = capturedState.emailVerificationCode, + newPassword = capturedState.newPassword, + ) + }.onSuccess { + postSideEffect(ResetPasswordSideEffect.PasswordReset) + }.onFailure { + it.printStackTrace() + postSideEffect(ResetPasswordSideEffect.PasswordFormatError) + } } - internal fun setRepeatPassword( - repeatPassword: String, - ) { - sendEvent(event = ChangePasswordEvent.SetRepeatPassword(repeatPassword)) - } + private fun checkIdExists() = viewModelScope.launch(Dispatchers.IO) { + val capturedState = stateFlow.value - internal fun setNewPassword( - newPassword: String, - ) { - sendEvent(event = ChangePasswordEvent.SetNewPassword(newPassword)) + runCatching { + authRepository.checkIdExists( + accountId = capturedState.accountId, + ) + }.onSuccess { + reduce( + newState = stateFlow.value.copy( + hashedEmail = it, + ), + ) + postSideEffect(ResetPasswordSideEffect.AccountIdExists) + }.onFailure { + postSideEffect(ResetPasswordSideEffect.AccountIdNotExists) + } } - override fun reduceEvent(oldState: ChangePasswordState, event: ChangePasswordEvent) { - when (event) { - is ChangePasswordEvent.SetCurrentPassword -> { - setState(state = oldState.copy(currentPassword = event.currentPassword)) - } - - is ChangePasswordEvent.SetRepeatPassword -> { - setState(state = oldState.copy(repeatPassword = event.repeatPassword)) + private fun sendEmailVerificationCode(email: String) = + runCatching { + viewModelScope.launch(Dispatchers.IO) { + authRepository.sendEmailVerificationCode( + email = email, + type = EmailVerificationType.PASSWORD, + ) } + }.onSuccess { + postSideEffect(ResetPasswordSideEffect.SendEmailVerificationCodeSuccess) + } - is ChangePasswordEvent.SetNewPassword -> { - setState(state = oldState.copy(newPassword = event.newPassword)) - } - else -> {} + private fun updateEmailVerificationCode(value: String) = run { + if (value.length > ResetPasswordViewModel.EMAIL_VERIFICATION_CODE_LENGTH) { + return@run false } + reduce(newState = stateFlow.value.copy(emailVerificationCode = value)) } - private fun event(event: Event) { - viewModelScope.launch { - _editPasswordEffect.emit(event) + private fun checkEmailVerificationCode() = viewModelScope.launch(Dispatchers.IO) { + val capturedState = stateFlow.value + runCatching { + authRepository.checkEmailVerificationCode( + email = capturedState.email, + code = capturedState.emailVerificationCode, + type = EmailVerificationType.PASSWORD, + ) + }.onSuccess { + postSideEffect(ResetPasswordSideEffect.EmailVerificationCodeChecked) + }.onFailure { + postSideEffect(ResetPasswordSideEffect.EmailVerificationCodeIncorrect) + reduce(newState = stateFlow.value.copy(emailVerificationCode = "")) } } - sealed class Event { - object EditPasswordSuccess : Event() - object ComparePasswordSuccess : Event() - data class CheckIdSuccess(val email: String) : Event() - object ResetPasswordSuccess : Event() - - object BadRequestException : Event() - object NotFoundException : Event() - object UnauthorizedException : Event() - object ForbiddenException : Event() - object TooManyRequestException : Event() - object ServerException : Event() - object UnknownException : Event() - } -} - -// TODO 추후에 리팩토링 필요 -private fun getEventFromThrowableChangePassword( - throwable: Throwable?, -): ChangePasswordViewModel.Event { - return when (throwable) { - else -> ChangePasswordViewModel.Event.UnknownException + private fun resetEmailVerificationSession() = viewModelScope.launch(Dispatchers.IO) { + runCatching { + this@ResetPasswordViewModel.sendEmailVerificationCode(email = stateFlow.value.email) + }.onSuccess { + postSideEffect(ResetPasswordSideEffect.EmailVerificationSessionReset) + reduce(newState = stateFlow.value.copy(emailVerificationCode = "")) + }.onFailure { + postSideEffect(ResetPasswordSideEffect.EmailVerificationSessionResetFailed) + } } -} -sealed class ChangePasswordEvent : MviEvent { - object ChangePasswordSuccess : ChangePasswordEvent() - object BadRequestException : ChangePasswordEvent() - object UnAuthorizedException : ChangePasswordEvent() - object NotFoundException : ChangePasswordEvent() - object TooManyRequestException : ChangePasswordEvent() - object InternalServerException : ChangePasswordEvent() - object UnKnownException : ChangePasswordEvent() + private fun updateNewPassword(value: String) = reduce( + newState = stateFlow.value.copy( + newPassword = value, + ) + ) + + private fun updateAccountId(value: String) = reduce( + newState = stateFlow.value.copy( + accountId = value, + ) + ) + + private fun updateStudentName(value: String) = reduce( + newState = stateFlow.value.copy( + studentName = value + ) + ) + + private fun updateEmail(value: String) = reduce( + newState = stateFlow.value.copy( + email = value, + ) + ) + + private fun updateNewPasswordRepeat(value: String) = reduce( + newState = stateFlow.value.copy( + newPasswordRepeat = value, + ) + ) - data class SetCurrentPassword(val currentPassword: String): ChangePasswordEvent() - data class SetRepeatPassword(val repeatPassword: String): ChangePasswordEvent() - data class SetNewPassword(val newPassword: String): ChangePasswordEvent() + companion object { + const val EMAIL_VERIFICATION_CODE_LENGTH = 6 + } } -data class ChangePasswordState( - val currentPassword: String, - val repeatPassword: String, +data class ResetPasswordUiState( + val accountId: String, + val studentName: String, + val email: String, + val emailVerificationCode: String, val newPassword: String, -) : _MviState { - + val newPasswordRepeat: String, + val hashedEmail: String, + val sessionId: UUID, +) : UiState() { companion object { - fun getDefaultInstance() = - ChangePasswordState( - currentPassword = "", - repeatPassword = "", - newPassword = "", - ) + fun initial() = ResetPasswordUiState( + accountId = "", + studentName = "", + email = "", + emailVerificationCode = "", + newPassword = "", + newPasswordRepeat = "", + hashedEmail = "", + sessionId = UUID.randomUUID(), + ) } } -@HiltViewModel -class ResetPasswordVerificationViewModel @Inject constructor( - private val sendEmailVerificationCodeUseCase: SendEmailVerificationCodeUseCase, - private val checkEmailVerificationCodeUseCase: CheckEmailVerificationCodeUseCase, - private val checkEmailDuplicationUseCase: CheckEmailDuplicationUseCase, -) : ViewModel() { - - private val _resetPasswordVerificationEvent = MutableEventFlow() - val registerEmailEvent = _resetPasswordVerificationEvent.asEventFlow() - - fun requestEmailCode( - email: String, - type: EmailVerificationType, - ) { - viewModelScope.launch { - kotlin.runCatching { - sendEmailVerificationCodeUseCase( - sendEmailVerificationCodeInput = SendEmailVerificationCodeInput( - email = email, - type = type, - ), - ) - }.onSuccess { - event(ResetPasswordVerificationEvent.SendEmailSuccess) - }.onFailure { - // fixme 추후에 리팩토링 필요 - when (it) { - else -> event(ResetPasswordVerificationEvent.UnKnownException) - } - } - } - } - - fun checkEmailCode( - email: String, - authCode: String, - type: EmailVerificationType, - ) { - viewModelScope.launch { - kotlin.runCatching { - checkEmailVerificationCodeUseCase( - checkEmailVerificationCodeInput = CheckEmailVerificationCodeInput( - email = email, - type = type, - authCode = authCode, - ), - ) - }.onSuccess { - event(ResetPasswordVerificationEvent.CheckEmailSuccess) - }.onFailure { - // fixme 추후에 리팩토링 필요 - when (it) { - else -> event(ResetPasswordVerificationEvent.InternalServerException) - } - } - } - } - - internal fun checkEmailDuplicate( - email: String, - ) { - viewModelScope.launch { - kotlin.runCatching { - checkEmailDuplicationUseCase( - checkEmailDuplicationInput = CheckEmailDuplicationInput( - email = email, - ), - ) - }.onSuccess { - event(ResetPasswordVerificationEvent.AllowEmail) - }.onFailure { - event(getEventFromThrowable(it)) - } - } - } - - private fun event(event: ResetPasswordVerificationEvent) { - viewModelScope.launch { - _resetPasswordVerificationEvent.emit(event) - } - } +sealed class ResetPasswordIntent : Intent() { + class UpdateNewPassword(val value: String) : ResetPasswordIntent() + class UpdateNewPasswordRepeat(val value: String) : ResetPasswordIntent() + data object SetPassword : ResetPasswordIntent() + class UpdateEmailVerificationCode(val value: String) : ResetPasswordIntent() + data object CheckEmailVerificationCode : ResetPasswordIntent() + data object ResetEmailVerificationSession : ResetPasswordIntent() + class UpdateAccountId(val value: String) : ResetPasswordIntent() + data object CheckAccountId : ResetPasswordIntent() + class UpdateStudentName(val value: String) : ResetPasswordIntent() + class UpdateEmail(val value: String) : ResetPasswordIntent() + class SendEmailVerificationCode(val value: String) : ResetPasswordIntent() } -// fixme 추후에 리팩토링 필요 -private fun getEventFromThrowable( - throwable: Throwable?, -): ResetPasswordVerificationEvent = - when (throwable) { - else -> { - ResetPasswordVerificationEvent.UnKnownException - } - } -sealed class ResetPasswordVerificationEvent : MviEvent { - object SendEmailSuccess : ResetPasswordVerificationEvent() - object CheckEmailSuccess : ResetPasswordVerificationEvent() - object BadRequestException : ResetPasswordVerificationEvent() - object CheckEmailNotFound : ResetPasswordVerificationEvent() - object CheckEmailUnauthorized : ResetPasswordVerificationEvent() - object TooManyRequestsException : ResetPasswordVerificationEvent() - object InternalServerException : ResetPasswordVerificationEvent() - object UnKnownException : ResetPasswordVerificationEvent() - - object AllowEmail: ResetPasswordVerificationEvent() - object ConflictException: ResetPasswordVerificationEvent() -} -*/ +sealed class ResetPasswordSideEffect : SideEffect() { + data object PasswordMismatch : ResetPasswordSideEffect() + data object PasswordFormatError : ResetPasswordSideEffect() + data object PasswordReset : ResetPasswordSideEffect() + data object InvalidPassword : ResetPasswordSideEffect() + data object AccountIdExists : ResetPasswordSideEffect() + data object AccountIdNotExists : ResetPasswordSideEffect() + data object SendEmailVerificationCodeSuccess : ResetPasswordSideEffect() + data object EmailVerificationCodeChecked : ResetPasswordSideEffect() + data object EmailVerificationCodeIncorrect : ResetPasswordSideEffect() + data object EmailVerificationSessionReset : ResetPasswordSideEffect() + data object EmailVerificationSessionResetFailed : ResetPasswordSideEffect() +} \ No newline at end of file From c7673654e37262739c90c4b4093ca39dafbdc3b9 Mon Sep 17 00:00:00 2001 From: chlgkdms Date: Thu, 14 Mar 2024 22:15:59 +0900 Subject: [PATCH 023/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20strings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/src/main/res/values/strings.xml | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index 5e02bc60e..b39dbe86f 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -290,4 +290,17 @@ %s 님이 맞으신가요? 새로고침 급식을 다시 불러왔습니다 + + + + 일치하는 아이디가 존재하지 않습니다. + 아이디 입력 + 본인확인 인증 + 아이디와 일치하는 이메일입니다. + 아이디 형식이 일치하지 않습니다. + 이름 입력 + 이메일 입력 + 비밀번호가 변경되었습니다. + 로그인 화면으로 + \ No newline at end of file From d87e34293ab899eef220d7bf36647932cd3fb387 Mon Sep 17 00:00:00 2001 From: chlgkdms Date: Thu, 14 Mar 2024 22:16:16 +0900 Subject: [PATCH 024/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20repository=20?= =?UTF-8?q?impl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/auth/repository/AuthRepositoryImpl.kt | 7 ++++--- .../data/student/repository/StudentRepositoryImpl.kt | 12 +++++++++++- 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/auth/repository/AuthRepositoryImpl.kt b/data/src/main/java/team/aliens/dms/android/data/auth/repository/AuthRepositoryImpl.kt index cd8d3d6aa..f040e1e3e 100644 --- a/data/src/main/java/team/aliens/dms/android/data/auth/repository/AuthRepositoryImpl.kt +++ b/data/src/main/java/team/aliens/dms/android/data/auth/repository/AuthRepositoryImpl.kt @@ -72,9 +72,10 @@ internal class AuthRepositoryImpl @Inject constructor( ) } - override suspend fun checkIdExists(accountId: String): HashedEmail { - TODO("Not yet implemented") - } + override suspend fun checkIdExists(accountId: String): HashedEmail = + networkAuthDataSource.checkIdExists( + accountId = accountId, + ).email override suspend fun signOut() { jwtProvider.clearCaches() diff --git a/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt b/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt index 13321c844..3a266df56 100644 --- a/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt +++ b/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt @@ -6,7 +6,9 @@ import team.aliens.dms.android.data.student.mapper.toModel import team.aliens.dms.android.data.student.model.HashedEmail import team.aliens.dms.android.data.student.model.MyPage import team.aliens.dms.android.data.student.model.StudentName +import team.aliens.dms.android.network.auth.datasource.NetworkAuthDataSource import team.aliens.dms.android.network.student.datasource.NetworkStudentDataSource +import team.aliens.dms.android.network.student.model.ResetPasswordRequest import team.aliens.dms.android.network.student.model.SignUpRequest import team.aliens.dms.android.network.student.model.SignUpResponse import team.aliens.dms.android.network.student.model.extractFeatures @@ -82,7 +84,15 @@ internal class StudentRepositoryImpl @Inject constructor( emailVerificationCode: String, newPassword: String, ) { - TODO("Not yet implemented") + networkStudentDataSource.resetPassword( + ResetPasswordRequest( + accountId = accountId, + studentName = studentName, + email = email, + emailVerificationCode = emailVerificationCode, + newPassword = newPassword, + ) + ) } override suspend fun checkIdDuplication(id: String) { From 111c2d7b663d5c8d44cac86584ceee973e4ec55a Mon Sep 17 00:00:00 2001 From: chlgkdms Date: Thu, 14 Mar 2024 22:16:27 +0900 Subject: [PATCH 025/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20data=20source?= =?UTF-8?q?=20impl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network/student/datasource/NetworkStudentDataSourceImpl.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/src/main/java/team/aliens/dms/android/network/student/datasource/NetworkStudentDataSourceImpl.kt b/network/src/main/java/team/aliens/dms/android/network/student/datasource/NetworkStudentDataSourceImpl.kt index 9941002d9..2acf9accb 100644 --- a/network/src/main/java/team/aliens/dms/android/network/student/datasource/NetworkStudentDataSourceImpl.kt +++ b/network/src/main/java/team/aliens/dms/android/network/student/datasource/NetworkStudentDataSourceImpl.kt @@ -44,7 +44,7 @@ internal class NetworkStudentDataSourceImpl @Inject constructor( number = number, ) - override suspend fun resetPassword(request: ResetPasswordRequest) = + override suspend fun resetPassword(request: ResetPasswordRequest): Unit = handleNetworkRequest { studentApiService.resetPassword(request) } override suspend fun checkIdDuplication(id: String) = From 126bfa0aee561c14780eca1c0a13678073ad72de Mon Sep 17 00:00:00 2001 From: ChoiHaeun <88268418+chlgkdms@users.noreply.github.com> Date: Thu, 14 Mar 2024 22:35:46 +0900 Subject: [PATCH 026/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20trailing=20co?= =?UTF-8?q?mma?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Junsu Park <101160207+JunJaBoy@users.noreply.github.com> --- .../android/data/student/repository/StudentRepositoryImpl.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt b/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt index 3a266df56..a32338de3 100644 --- a/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt +++ b/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt @@ -91,7 +91,7 @@ internal class StudentRepositoryImpl @Inject constructor( email = email, emailVerificationCode = emailVerificationCode, newPassword = newPassword, - ) + ), ) } From 3a8be2f1b0f8590b99416fbd8953484aa72adb44 Mon Sep 17 00:00:00 2001 From: chlgkdms Date: Thu, 14 Mar 2024 22:47:46 +0900 Subject: [PATCH 027/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20strings?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../1_AccountVerificationScreen.kt | 14 +++++------ .../resetpassword/3_SetPasswordScreen.kt | 23 +++++++++++++------ feature/src/main/res/values/strings.xml | 20 ++++++++-------- 3 files changed, 33 insertions(+), 24 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/1_AccountVerificationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/1_AccountVerificationScreen.kt index 0d4f8b533..17b83340d 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/1_AccountVerificationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/1_AccountVerificationScreen.kt @@ -77,7 +77,7 @@ fun AccountVerificationScreen( } ResetPasswordSideEffect.AccountIdNotExists -> toast.showErrorToast( - message = context.getString(R.string.reset_password_account_id_does_not_exist), + message = context.getString(R.string.reset_password_account_verification_account_id_does_not_exist), ) ResetPasswordSideEffect.SendEmailVerificationCodeSuccess -> navigator.openResetPasswordEnterEmailVerificationCode() @@ -118,7 +118,7 @@ fun AccountVerificationScreen( .topPadding(BannerDefaults.DefaultTopSpace) .startPadding(), message = { - BannerDefaults.DefaultText(text = stringResource(id = R.string.reset_password_identification_verification)) + BannerDefaults.DefaultText(text = stringResource(id = R.string.reset_password_account_verification_identification_verification)) }, ) Spacer(modifier = Modifier.weight(1f)) @@ -128,11 +128,11 @@ fun AccountVerificationScreen( .horizontalPadding(), value = uiState.accountId, hint = { - Text(text = stringResource(id = R.string.reset_password_enter_account_id)) + Text(text = stringResource(id = R.string.reset_password_account_verification_enter_account_id)) }, onValueChange = { viewModel.postIntent(ResetPasswordIntent.UpdateAccountId(value = it)) }, supportingText = if (isAccountIdError) { - { Text(text = stringResource(id = R.string.reset_password_enter_account_id_error_invalid_format)) } + { Text(text = stringResource(id = R.string.reset_password_account_verification_enter_account_id_invalid_format)) } } else { null }, @@ -159,7 +159,7 @@ fun AccountVerificationScreen( .horizontalPadding(), value = uiState.studentName, hint = { - Text(text = stringResource(id = R.string.reset_password_enter_student_name)) + Text(text = stringResource(id = R.string.reset_password_account_verification_enter_student_name)) }, onValueChange = { viewModel.postIntent(ResetPasswordIntent.UpdateStudentName(value = it)) @@ -171,7 +171,7 @@ fun AccountVerificationScreen( .horizontalPadding(), value = uiState.email, hint = { - Text(text = stringResource(id = R.string.reset_password_enter_email)) + Text(text = stringResource(id = R.string.reset_password_account_verification_enter_email)) }, onValueChange = { viewModel.postIntent(ResetPasswordIntent.UpdateEmail(value = it)) @@ -224,7 +224,7 @@ private fun AccountAssertionCard( ) { Text( modifier = Modifier.startPadding(), - text = stringResource(id = R.string.reset_password_account_id_match_email), + text = stringResource(id = R.string.reset_password_account_verification_success_account_id_matches_email), ) Text( modifier = Modifier.startPadding(), diff --git a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/3_SetPasswordScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/3_SetPasswordScreen.kt index 43b45b6ba..4786eee56 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/3_SetPasswordScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/3_SetPasswordScreen.kt @@ -20,7 +20,6 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource -import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.AlertDialog @@ -40,8 +39,6 @@ import team.aliens.dms.android.core.ui.startPadding import team.aliens.dms.android.core.ui.topPadding import team.aliens.dms.android.feature.R import team.aliens.dms.android.feature.resetpassword.navigation.ResetPasswordNavigator -import team.aliens.dms.android.feature.signup.SignUpIntent -import team.aliens.dms.android.feature.signup.SignUpSideEffect @Suppress("ConstPropertyName") private const val passwordFormat = "^(?=.*[A-Za-z])(?=.*[0-9])(?=.*[!@#$%^&*()_+=-]).{8,20}" @@ -68,13 +65,13 @@ fun ResetPasswordSetPasswordScreen( if (shouldShowQuitSignUpDialog) { AlertDialog( - text = { Text(text = stringResource(id = R.string.reset_password_password_changed)) }, + text = { Text(text = stringResource(id = R.string.reset_password_set_password_password_success_changed)) }, onDismissRequest = { /* explicit blank */ }, confirmButton = { TextButton( onClick = navigator::openSignIn, ) { - Text(text = stringResource(id = R.string.reset_password_go_sign_in_screen)) + Text(text = stringResource(id = R.string.reset_password_go_to_sign_in_screen)) } }, ) @@ -138,7 +135,13 @@ fun ResetPasswordSetPasswordScreen( .fillMaxWidth() .horizontalPadding(), value = uiState.newPassword, - onValueChange = { viewModel.postIntent(ResetPasswordIntent.UpdateNewPassword(value = it)) }, + onValueChange = { + viewModel.postIntent( + ResetPasswordIntent.UpdateNewPassword( + value = it + ) + ) + }, passwordShowing = showPassword, onPasswordShowingChange = onShowPasswordChange, hintText = stringResource(id = R.string.edit_password_please_enter_new_password) @@ -148,7 +151,13 @@ fun ResetPasswordSetPasswordScreen( .fillMaxWidth() .horizontalPadding(), value = uiState.newPasswordRepeat, - onValueChange = { viewModel.postIntent(ResetPasswordIntent.UpdateNewPasswordRepeat(value = it)) }, + onValueChange = { + viewModel.postIntent( + ResetPasswordIntent.UpdateNewPasswordRepeat( + value = it + ) + ) + }, passwordShowing = showPasswordRepeat, onPasswordShowingChange = onShowPasswordRepeatChange, hintText = stringResource(id = R.string.edit_password_please_enter_new_password_repeat) diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index b39dbe86f..7b84fd0fa 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -170,7 +170,7 @@ 비밀번호는 영문, 숫자, 기호를 포함한 8~20자이어야 합니다 - 로그인 화면으로 + 로그인 화면으로 %s 으로 아이디가 전송되었습니다 학교를 선택해주세요 @@ -293,14 +293,14 @@ - 일치하는 아이디가 존재하지 않습니다. - 아이디 입력 - 본인확인 인증 - 아이디와 일치하는 이메일입니다. - 아이디 형식이 일치하지 않습니다. - 이름 입력 - 이메일 입력 - 비밀번호가 변경되었습니다. - 로그인 화면으로 + 일치하는 아이디가 존재하지 않습니다. + 아이디 입력 + 본인확인 인증 + 아이디와 일치하는 이메일입니다 + 아이디 형식이 일치하지 않습니다. + 이름 입력 + 이메일 입력 + 비밀번호가 변경되었습니다. + 로그인 화면으로 \ No newline at end of file From feefdb535e5046a99cc4b50682c9e33cf5bec4d0 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 09:31:54 +0900 Subject: [PATCH 028/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20response?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/network/outing/model/ApplyOutingRequest.kt | 8 +++++--- .../model/FetchCurrentAppliedOutingApplicationResponse.kt | 8 +++++--- .../outing/model/FetchOutingApplicationDetailsResponse.kt | 5 +++-- .../network/outing/model/OutingAvailableTimeResponse.kt | 5 +++-- 4 files changed, 16 insertions(+), 10 deletions(-) diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt index e37f5966c..4dbb949c7 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt @@ -1,12 +1,14 @@ package team.aliens.dms.android.network.outing.model import com.google.gson.annotations.SerializedName +import org.threeten.bp.LocalDate +import org.threeten.bp.LocalDateTime import java.util.UUID data class ApplyOutingRequest( - @SerializedName("out_at") val date: String, - @SerializedName("outing_time") val startTime: String, - @SerializedName("arrival_time") val endTime: String, + @SerializedName("outing_date") val date: LocalDate, + @SerializedName("outing_time") val startTime: LocalDateTime, + @SerializedName("arrival_time") val endTime: LocalDateTime, @SerializedName("outing_type_title") val type: String, @SerializedName("reason") val reason: String?, @SerializedName("companion_ids") val followerIds: List, diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt index 15f34df80..7966594a3 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt @@ -1,13 +1,15 @@ package team.aliens.dms.android.network.outing.model import com.google.gson.annotations.SerializedName +import org.threeten.bp.LocalDate +import org.threeten.bp.LocalDateTime data class FetchCurrentAppliedOutingApplicationResponse( - @SerializedName("out_at") val date: String, + @SerializedName("outing_date") val date: LocalDate, @SerializedName("outing_type") val type: String, @SerializedName("status") val status: String, - @SerializedName("outing_time") val startTime: String, - @SerializedName("arrival_time") val endTime: String, + @SerializedName("outing_time") val startTime: LocalDateTime, + @SerializedName("arrival_time") val endTime: LocalDateTime, @SerializedName("reason") val reason: String?, @SerializedName("outing_companions") val followerNames: List, ) diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchOutingApplicationDetailsResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchOutingApplicationDetailsResponse.kt index 547bf01cc..7869e7b83 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchOutingApplicationDetailsResponse.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchOutingApplicationDetailsResponse.kt @@ -1,11 +1,12 @@ package team.aliens.dms.android.network.outing.model import com.google.gson.annotations.SerializedName +import org.threeten.bp.LocalDateTime import java.util.UUID data class FetchOutingApplicationDetailsResponse( - @SerializedName("outing_time") val startTime: String, - @SerializedName("arrival_time") val endTime: String, + @SerializedName("outing_time") val startTime: LocalDateTime, + @SerializedName("arrival_time") val endTime: LocalDateTime, @SerializedName("outing_status") val status: String, @SerializedName("reason") val reason: String?, @SerializedName("outing_type") val type: String, diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt index ad950770e..444f8e3bf 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt @@ -1,14 +1,15 @@ package team.aliens.dms.android.network.outing.model import com.google.gson.annotations.SerializedName +import org.threeten.bp.LocalDateTime data class OutingAvailableTimeResponse( @SerializedName("outing_available_time") val availableTimes: List, ) { data class AvailableTimeResponse( @SerializedName("outing_available_time_id") val outingAvailableTimeId: String, - @SerializedName("outing_time") val startTime: String, - @SerializedName("arrival_time") val endTime: String, + @SerializedName("outing_time") val startTime: LocalDateTime, + @SerializedName("arrival_time") val endTime: LocalDateTime, @SerializedName("enabled") val available: Boolean, @SerializedName("day_of_week") val dayOfWeek: String, ) From 1b219e7e44ad6c154db200638f8ea0f692e4336b Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 09:32:22 +0900 Subject: [PATCH 029/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20dms=20app?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/aliens/dms/android/app/DmsApp.kt | 45 +------------------ 1 file changed, 1 insertion(+), 44 deletions(-) diff --git a/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt b/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt index 10b483dd9..576569bcd 100644 --- a/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt +++ b/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt @@ -1,10 +1,5 @@ package team.aliens.dms.android.app -import androidx.compose.animation.AnimatedContentTransitionScope -import androidx.compose.animation.EnterTransition -import androidx.compose.animation.ExperimentalAnimationApi -import androidx.compose.animation.core.tween -import androidx.compose.animation.fadeOut import androidx.compose.material3.windowsizeclass.WindowSizeClass import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -14,20 +9,13 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import androidx.navigation.NavDestination import androidx.navigation.NavDestination.Companion.hierarchy import androidx.window.layout.DisplayFeature -import com.google.accompanist.navigation.material.ExperimentalMaterialNavigationApi import com.ramcosta.composedestinations.DestinationsNavHost -import com.ramcosta.composedestinations.animations.defaults.NestedNavGraphDefaultAnimations -import com.ramcosta.composedestinations.animations.defaults.RootNavGraphDefaultAnimations -import com.ramcosta.composedestinations.animations.rememberAnimatedNavHostEngine import com.ramcosta.composedestinations.navigation.dependency import com.ramcosta.composedestinations.scope.DestinationScopeWithNoDependencies import com.ramcosta.composedestinations.spec.NavGraphSpec -import com.ramcosta.composedestinations.spec.NavHostEngine import kotlinx.coroutines.flow.StateFlow import team.aliens.dms.android.app.navigation.DmsNavGraph import team.aliens.dms.android.app.navigation.DmsNavigator -import team.aliens.dms.android.app.navigation.authorized.AuthorizedNavGraph -import team.aliens.dms.android.app.navigation.unauthorized.UnauthorizedNavGraph import team.aliens.dms.android.feature.destinations.TermsScreenDestination import team.aliens.dms.android.feature.editpassword.EditPasswordViewModel import team.aliens.dms.android.feature.editpassword.navigation.EditPasswordNavGraph @@ -39,16 +27,14 @@ import team.aliens.dms.android.feature.signup.navigation.SignUpNavGraph fun DmsApp( windowSizeClass: WindowSizeClass, displayFeatures: List, - engine: NavHostEngine = rememberDmsNavHostEngine(), isJwtAvailable: StateFlow, appState: DmsAppState = rememberDmsAppState( - navController = engine.rememberNavController(), isJwtAvailable = isJwtAvailable, ), ) { val autoSignIn by appState.isJwtAvailable.collectAsStateWithLifecycle() DestinationsNavHost( - engine = engine, + engine = appState.engine, navGraph = DmsNavGraph.root(autoSignIn = autoSignIn), navController = appState.navController, dependenciesContainerBuilder = { @@ -73,35 +59,6 @@ fun DmsApp( ) } -@OptIn(ExperimentalMaterialNavigationApi::class, ExperimentalAnimationApi::class) -@Composable -private fun rememberDmsNavHostEngine() = rememberAnimatedNavHostEngine( - rootDefaultAnimations = RootNavGraphDefaultAnimations.ACCOMPANIST_FADING, - defaultAnimationsForNestedNavGraph = mapOf( - AuthorizedNavGraph to NestedNavGraphDefaultAnimations( - enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Start) }, - exitTransition = { fadeOut(tween(delayMillis = 10)) }, - popEnterTransition = { EnterTransition.None }, - popExitTransition = { - slideOutOfContainer( - towards = AnimatedContentTransitionScope.SlideDirection.End, - animationSpec = tween(delayMillis = 10), - ) - }, - ), UnauthorizedNavGraph to NestedNavGraphDefaultAnimations( - enterTransition = { slideIntoContainer(AnimatedContentTransitionScope.SlideDirection.Start) }, - exitTransition = { fadeOut(tween(delayMillis = 10)) }, - popEnterTransition = { EnterTransition.None }, - popExitTransition = { - slideOutOfContainer( - towards = AnimatedContentTransitionScope.SlideDirection.End, - animationSpec = tween(delayMillis = 10), - ) - }, - ) - ), -) - private fun DestinationScopeWithNoDependencies<*>.currentNavigator(autoSignIn: Boolean): DmsNavigator = DmsNavigator( navGraph = navBackStackEntry.destination.navGraph(autoSignIn), From 7bcaaf39f73d919e2189b9d5c1651c4ea990a2cf Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 09:32:30 +0900 Subject: [PATCH 030/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20app=20state?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/team/aliens/dms/android/app/DmsAppState.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/team/aliens/dms/android/app/DmsAppState.kt b/app/src/main/java/team/aliens/dms/android/app/DmsAppState.kt index 05389769e..06ee12b93 100644 --- a/app/src/main/java/team/aliens/dms/android/app/DmsAppState.kt +++ b/app/src/main/java/team/aliens/dms/android/app/DmsAppState.kt @@ -46,6 +46,7 @@ fun rememberDmsAppState( context: Context = LocalContext.current, ) = remember(navController, context) { DmsAppState( + engine = engine, navController = navController, isJwtAvailable = isJwtAvailable, context = context, @@ -53,6 +54,7 @@ fun rememberDmsAppState( } class DmsAppState( + val engine: NavHostEngine, val navController: NavHostController, val isJwtAvailable: StateFlow, private val context: Context, From 2a08054d19f35e82e08fb30ddfc41c9c63af881e Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 09:49:08 +0900 Subject: [PATCH 031/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20id?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/data/outing/model/OutingApplicationId.kt | 5 +++++ 1 file changed, 5 insertions(+) create mode 100644 data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationId.kt diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationId.kt b/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationId.kt new file mode 100644 index 000000000..ea198fe0b --- /dev/null +++ b/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationId.kt @@ -0,0 +1,5 @@ +package team.aliens.dms.android.data.outing.model + +import java.util.UUID + +typealias OutingApplicationId = UUID From c405e177968d9c6aeb4657d0cd41873427a6078a Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 09:50:45 +0900 Subject: [PATCH 032/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20req?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/data/outing/model/OutingApplicationTime.kt | 5 +++++ .../dms/android/network/outing/model/ApplyOutingRequest.kt | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) create mode 100644 data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt b/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt new file mode 100644 index 000000000..13f9cb781 --- /dev/null +++ b/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt @@ -0,0 +1,5 @@ +package team.aliens.dms.android.data.outing.model + +data class OutingApplicationTime( + +) diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt index 4dbb949c7..c87d78aed 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt @@ -11,5 +11,5 @@ data class ApplyOutingRequest( @SerializedName("arrival_time") val endTime: LocalDateTime, @SerializedName("outing_type_title") val type: String, @SerializedName("reason") val reason: String?, - @SerializedName("companion_ids") val followerIds: List, + @SerializedName("companion_ids") val companionIds: List, ) From fb9e9d9bad441afdda02fe0fe61b3f4023f6c364 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 10:22:51 +0900 Subject: [PATCH 033/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20application?= =?UTF-8?q?=20time?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/data/outing/model/OutingApplicationTime.kt | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt b/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt index 13f9cb781..cf1036462 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt @@ -1,5 +1,13 @@ package team.aliens.dms.android.data.outing.model -data class OutingApplicationTime( +import org.threeten.bp.DayOfWeek +import org.threeten.bp.LocalDateTime +import java.util.UUID +data class OutingApplicationTime( + val id: UUID, + val startTime: LocalDateTime, + val endTime: LocalDateTime, + val enabled: Boolean, + val dayOfWeek: DayOfWeek, ) From a7622c53bc2b3aa27a06f3dd53c7bfb3a73d4245 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 10:25:34 +0900 Subject: [PATCH 034/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20application?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/CurrentAppliedOutingApplication.kt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt b/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt new file mode 100644 index 000000000..f257cc39f --- /dev/null +++ b/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt @@ -0,0 +1,19 @@ +package team.aliens.dms.android.data.outing.model + +import org.threeten.bp.LocalDate +import org.threeten.bp.LocalDateTime + +data class CurrentAppliedOutingApplication( + val date: LocalDate, + val type: String, + val status: OutingStatus, + val startTime: LocalDateTime, + val endTime: LocalDateTime, + val reason: String?, + val companionNames: List, +) { + // TODO + enum class OutingStatus { + DONE, REJECTED, ; + } +} From 96222f36b9ddcb00839d6f9f571750bc009d57a1 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 10:27:16 +0900 Subject: [PATCH 035/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20response?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/network/outing/model/FetchOutingTypesResponse.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchOutingTypesResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchOutingTypesResponse.kt index eaaa75b13..8c64f8b40 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchOutingTypesResponse.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchOutingTypesResponse.kt @@ -3,5 +3,5 @@ package team.aliens.dms.android.network.outing.model import com.google.gson.annotations.SerializedName data class FetchOutingTypesResponse( - @SerializedName("titles") val titles: String, + @SerializedName("titles") val titles: List, ) From 095ba39878a0b767ee652cc3047c7d7cd9db5481 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 10:27:28 +0900 Subject: [PATCH 036/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20datasource?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network/outing/datasource/OutingNetworkDataSource.kt | 2 +- .../network/outing/datasource/OutingNetworkDataSourceImpl.kt | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSource.kt b/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSource.kt index 326b6b0a9..5517bda77 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSource.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSource.kt @@ -10,7 +10,7 @@ import team.aliens.dms.android.network.outing.model.OutingAvailableTimeResponse import java.util.UUID abstract class OutingNetworkDataSource { - abstract fun fetchOutingAvailableTime(type: String): OutingAvailableTimeResponse + abstract fun fetchOutingAvailableTime(dayOfWeek: String): OutingAvailableTimeResponse abstract fun applyOuting(req: ApplyOutingRequest): ApplyOutingResponse abstract fun fetchOutingApplicationDetails(applicationId: UUID): FetchOutingApplicationDetailsResponse abstract fun fetchCurrentAppliedOutingApplication(): FetchCurrentAppliedOutingApplicationResponse diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSourceImpl.kt b/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSourceImpl.kt index d87d30637..afcb569cf 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSourceImpl.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSourceImpl.kt @@ -14,8 +14,8 @@ import javax.inject.Inject class OutingNetworkDataSourceImpl @Inject constructor( private val outingApiService: OutingApiService, ) : OutingNetworkDataSource() { - override fun fetchOutingAvailableTime(type: String): OutingAvailableTimeResponse = - outingApiService.fetchOutingAvailableTime(type) + override fun fetchOutingAvailableTime(dayOfWeek: String): OutingAvailableTimeResponse = + outingApiService.fetchOutingAvailableTime(dayOfWeek) override fun applyOuting(req: ApplyOutingRequest): ApplyOutingResponse = outingApiService.applyOuting(req) From 9fb44bb90512f0847b35f44fd1b53affe13fe4c1 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 10:27:31 +0900 Subject: [PATCH 037/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20string?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/src/main/res/values/strings.xml | 3 +++ 1 file changed, 3 insertions(+) diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index 68643e14b..91b8a702f 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -287,4 +287,7 @@ 번호 %s 님이 맞으신가요? + + + 외출 신청 \ No newline at end of file From fa43b1fa668244ddd2b857e2ea59e19cd7f2406b Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 20:28:40 +0900 Subject: [PATCH 038/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20application?= =?UTF-8?q?=20time?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/outing/model/OutingApplicationTime.kt | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt b/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt index cf1036462..6622309c2 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt @@ -2,12 +2,28 @@ package team.aliens.dms.android.data.outing.model import org.threeten.bp.DayOfWeek import org.threeten.bp.LocalDateTime +import team.aliens.dms.android.network.outing.model.OutingAvailableTimeResponse import java.util.UUID data class OutingApplicationTime( val id: UUID, val startTime: LocalDateTime, val endTime: LocalDateTime, - val enabled: Boolean, + val available: Boolean, val dayOfWeek: DayOfWeek, ) + +fun OutingAvailableTimeResponse.toModel(): List = + this.availableTimes.map(OutingAvailableTimeResponse.AvailableTimeResponse::toModel) + +fun List.toModel(): List = + this.map(OutingAvailableTimeResponse.AvailableTimeResponse::toModel) + +fun OutingAvailableTimeResponse.AvailableTimeResponse.toModel(): OutingApplicationTime = + OutingApplicationTime( + id = UUID.fromString(this.outingAvailableTimeId), + startTime = this.startTime, + endTime = this.endTime, + available = this.available, + dayOfWeek = DayOfWeek.valueOf(this.dayOfWeek), + ) From 8ebab29ddf1595c183d60b6a1c52e2b12a61abce Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 20:30:00 +0900 Subject: [PATCH 039/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20type?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/network/outing/model/ApplyOutingResponse.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingResponse.kt index 1596e1aed..fbfef2743 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingResponse.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingResponse.kt @@ -1,7 +1,8 @@ package team.aliens.dms.android.network.outing.model import com.google.gson.annotations.SerializedName +import java.util.UUID data class ApplyOutingResponse( - @SerializedName("outing_application_id") val applicationId: String, + @SerializedName("outing_application_id") val applicationId: UUID, ) From 46aec0d7022ec2709b6573765cf333bb6dcc2ff0 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 20:30:21 +0900 Subject: [PATCH 040/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20application?= =?UTF-8?q?=20enum?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/outing/model/CurrentAppliedOutingApplication.kt | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt b/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt index f257cc39f..1f31661c3 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt @@ -14,6 +14,10 @@ data class CurrentAppliedOutingApplication( ) { // TODO enum class OutingStatus { - DONE, REJECTED, ; + REQUESTED, + OUTING, + DONE, ; } } + + From cb3f955e877aeed930effa3f1abc89b3a42d1bb3 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 20:31:46 +0900 Subject: [PATCH 041/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20model?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/CurrentAppliedOutingApplication.kt | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt b/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt index 1f31661c3..f136c2345 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt @@ -2,6 +2,7 @@ package team.aliens.dms.android.data.outing.model import org.threeten.bp.LocalDate import org.threeten.bp.LocalDateTime +import team.aliens.dms.android.network.outing.model.FetchCurrentAppliedOutingApplicationResponse data class CurrentAppliedOutingApplication( val date: LocalDate, @@ -14,10 +15,17 @@ data class CurrentAppliedOutingApplication( ) { // TODO enum class OutingStatus { - REQUESTED, - OUTING, - DONE, ; + REQUESTED, OUTING, DONE, ; } } - +fun FetchCurrentAppliedOutingApplicationResponse.toModel(): CurrentAppliedOutingApplication = + CurrentAppliedOutingApplication( + date = this.date, + type = this.type, + status = CurrentAppliedOutingApplication.OutingStatus.valueOf(this.status), + startTime = this.startTime, + endTime = this.endTime, + reason = this.reason, + companionNames = this.companionNames, + ) From ea1be68c0c3066f2aa54bdfd5ccae02aeb79b904 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 20:31:54 +0900 Subject: [PATCH 042/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20response=20ty?= =?UTF-8?q?pe?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/FetchCurrentAppliedOutingApplicationResponse.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt index 7966594a3..e5c629a76 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt @@ -11,5 +11,5 @@ data class FetchCurrentAppliedOutingApplicationResponse( @SerializedName("outing_time") val startTime: LocalDateTime, @SerializedName("arrival_time") val endTime: LocalDateTime, @SerializedName("reason") val reason: String?, - @SerializedName("outing_companions") val followerNames: List, + @SerializedName("outing_companions") val companionNames: List, ) From 98ff1105a918a617abf85e8abbe3a1c1a50bcff1 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 20:31:59 +0900 Subject: [PATCH 043/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20repository=20?= =?UTF-8?q?impl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../outing/repository/OutingRepository.kt | 23 +++++++++++ .../outing/repository/OutingRepositoryImpl.kt | 39 +++++++++++++++++++ 2 files changed, 62 insertions(+) diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt index 900a73d28..da8ae9f0f 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt @@ -1,5 +1,28 @@ package team.aliens.dms.android.data.outing.repository +import org.threeten.bp.DayOfWeek +import org.threeten.bp.LocalDate +import org.threeten.bp.LocalDateTime +import team.aliens.dms.android.data.outing.model.CurrentAppliedOutingApplication +import team.aliens.dms.android.data.outing.model.OutingApplicationId +import team.aliens.dms.android.data.outing.model.OutingApplicationTime +import java.util.UUID + abstract class OutingRepository { + abstract fun fetchOutingApplicationTimes(dayOfWeek: DayOfWeek): List + + abstract fun applyOuting( + date: LocalDate, + startTime: LocalDateTime, + endTime: LocalDateTime, + type: String, + reason: String?, + companionIds: List, + ): OutingApplicationId + + abstract fun fetchCurrentAppliedOutingApplication(): CurrentAppliedOutingApplication + + abstract fun cancelOuting(applicationId: UUID) + abstract fun fetchOutingTypes(keyword: String): List } diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt index 776dda0b9..28e9190da 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt @@ -1,9 +1,48 @@ package team.aliens.dms.android.data.outing.repository +import org.threeten.bp.DayOfWeek +import org.threeten.bp.LocalDate +import org.threeten.bp.LocalDateTime +import team.aliens.dms.android.data.outing.model.CurrentAppliedOutingApplication +import team.aliens.dms.android.data.outing.model.OutingApplicationId +import team.aliens.dms.android.data.outing.model.OutingApplicationTime +import team.aliens.dms.android.data.outing.model.toModel +import team.aliens.dms.android.network.outing.datasource.OutingNetworkDataSource +import team.aliens.dms.android.network.outing.model.ApplyOutingRequest +import java.util.UUID import javax.inject.Inject class OutingRepositoryImpl @Inject constructor( private val outingNetworkDataSource: OutingNetworkDataSource, ) : OutingRepository() { + override fun fetchOutingApplicationTimes(dayOfWeek: DayOfWeek): List = + outingNetworkDataSource.fetchOutingAvailableTime(dayOfWeek = dayOfWeek.name).toModel() + override fun applyOuting( + date: LocalDate, + startTime: LocalDateTime, + endTime: LocalDateTime, + type: String, + reason: String?, + companionIds: List + ): OutingApplicationId = outingNetworkDataSource.applyOuting( + req = ApplyOutingRequest( + date = date, + startTime = startTime, + endTime = endTime, + type = type, + reason = reason, + companionIds = companionIds, + ), + ).applicationId + + override fun fetchCurrentAppliedOutingApplication(): CurrentAppliedOutingApplication = + outingNetworkDataSource.fetchCurrentAppliedOutingApplication().toModel() + + override fun cancelOuting(applicationId: UUID) { + outingNetworkDataSource.cancelOuting(applicationId = applicationId) + } + + override fun fetchOutingTypes(keyword: String): List = + outingNetworkDataSource.fetchOutingTypes(keyword = keyword).titles } From c1c01ec864e63a98aa26cc20a5ac461643a35411 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 20:42:19 +0900 Subject: [PATCH 044/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20nav?= =?UTF-8?q?=20graph?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../outing/navigation/OutingNavGraph.kt | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) create mode 100644 feature/src/main/java/team/aliens/dms/android/feature/outing/navigation/OutingNavGraph.kt diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/navigation/OutingNavGraph.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/navigation/OutingNavGraph.kt new file mode 100644 index 000000000..30943b7f4 --- /dev/null +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/navigation/OutingNavGraph.kt @@ -0,0 +1,19 @@ +package team.aliens.dms.android.feature.outing.navigation + +import com.ramcosta.composedestinations.dynamic.routedIn +import com.ramcosta.composedestinations.spec.DestinationSpec +import com.ramcosta.composedestinations.spec.NavGraphSpec +import com.ramcosta.composedestinations.spec.Route +import team.aliens.dms.android.feature.destinations.OutingApplicationScreenDestination +import team.aliens.dms.android.feature.destinations.OutingStatusScreenDestination + +object OutingNavGraph : NavGraphSpec { + override val route: String = "outing" + override val startRoute: Route = OutingStatusScreenDestination routedIn this + override val destinationsByRoute: Map> = listOf>( + OutingStatusScreenDestination, + OutingApplicationScreenDestination, + ) + .routedIn(navGraphSpec = this) + .associateBy { it.route } +} From 75944afd7886f7aa2aa92808a2f4f53d676b3330 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 20:42:22 +0900 Subject: [PATCH 045/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20authorized?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/app/navigation/authorized/AuthorizedNavGraph.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/team/aliens/dms/android/app/navigation/authorized/AuthorizedNavGraph.kt b/app/src/main/java/team/aliens/dms/android/app/navigation/authorized/AuthorizedNavGraph.kt index ea8b5f01f..0f3444d66 100644 --- a/app/src/main/java/team/aliens/dms/android/app/navigation/authorized/AuthorizedNavGraph.kt +++ b/app/src/main/java/team/aliens/dms/android/app/navigation/authorized/AuthorizedNavGraph.kt @@ -14,6 +14,7 @@ import team.aliens.dms.android.feature.destinations.RemainsApplicationScreenDest import team.aliens.dms.android.feature.destinations.StudyRoomDetailsScreenDestination import team.aliens.dms.android.feature.destinations.StudyRoomListScreenDestination import team.aliens.dms.android.feature.editpassword.navigation.EditPasswordNavGraph +import team.aliens.dms.android.feature.outing.navigation.OutingNavGraph import team.aliens.dms.android.feature.studyroom.navigation.StudyRoomNavGraph object AuthorizedNavGraph : NavGraphSpec { @@ -23,6 +24,7 @@ object AuthorizedNavGraph : NavGraphSpec { listOf( EditPasswordNavGraph, StudyRoomNavGraph, + OutingNavGraph, ) override val destinationsByRoute: Map> = From 3d22b3ef2c98d4c5c9d465143fd7a4bfda85f344 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 20:44:16 +0900 Subject: [PATCH 046/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20scaffold?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/core/designsystem/Scaffold.kt | 50 +------------------ .../editpassword/1_ConfirmPasswordScreen.kt | 4 +- .../editpassword/2_SetPasswordScreen.kt | 4 +- .../aliens/dms/android/feature/main/Main.kt | 4 +- .../announcement/AnnouncementListScreen.kt | 4 +- .../main/application/ApplicationScreen.kt | 4 +- .../android/feature/main/home/HomeScreen.kt | 4 +- .../feature/main/mypage/MyPageScreen.kt | 4 +- .../feature/notice/NoticeDetailsScreen.kt | 4 +- .../feature/point/PointHistoryScreen.kt | 4 +- .../remains/RemainsApplicationScreen.kt | 4 +- .../android/feature/signin/SignInScreen.kt | 7 ++- .../1_EnterSchoolVerificationCodeScreen.kt | 4 +- ...2_EnterSchoolVerificationQuestionScreen.kt | 4 +- .../feature/signup/3_EnterEmailScreen.kt | 4 +- .../4_EnterEmailVerificationCodeScreen.kt | 5 +- .../android/feature/signup/5_SetIdScreen.kt | 4 +- .../feature/signup/6_SetPasswordScreen.kt | 4 +- .../android/feature/signup/8_TermsScreen.kt | 4 +- .../details/StudyRoomDetailsScreen.kt | 4 +- .../studyroom/list/StudyRoomListScreen.kt | 4 +- 21 files changed, 42 insertions(+), 92 deletions(-) diff --git a/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Scaffold.kt b/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Scaffold.kt index 19d663866..c05633705 100644 --- a/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Scaffold.kt +++ b/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Scaffold.kt @@ -1,25 +1,15 @@ package team.aliens.dms.android.core.designsystem -import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.WindowInsets -import androidx.compose.material3.BottomSheetDefaults -import androidx.compose.material3.BottomSheetScaffold -import androidx.compose.material3.BottomSheetScaffoldState -import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Scaffold import androidx.compose.material3.ScaffoldDefaults -import androidx.compose.material3.SnackbarHost -import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.rememberBottomSheetScaffoldState import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color -import androidx.compose.ui.graphics.Shape -import androidx.compose.ui.unit.Dp @Composable -fun DmsScaffold( +fun Scaffold( modifier: Modifier = Modifier, topBar: @Composable () -> Unit = {}, bottomBar: @Composable () -> Unit = {}, @@ -36,41 +26,3 @@ fun DmsScaffold( contentWindowInsets = contentWindowInsets, content = content, ) - -@OptIn(ExperimentalMaterial3Api::class) -@Composable -fun DmsBottomSheetScaffold( - sheetContent: @Composable ColumnScope.() -> Unit, - modifier: Modifier = Modifier, - scaffoldState: BottomSheetScaffoldState = rememberBottomSheetScaffoldState(), - sheetPeekHeight: Dp = BottomSheetDefaults.SheetPeekHeight, - sheetShape: Shape = BottomSheetDefaults.ExpandedShape, - sheetContainerColor: Color = DmsTheme.colorScheme.surface, - sheetContentColor: Color = DmsTheme.colorScheme.onSurface, - sheetTonalElevation: Dp = BottomSheetDefaults.Elevation, - sheetShadowElevation: Dp = BottomSheetDefaults.Elevation, - sheetDragHandle: @Composable (() -> Unit)? = { BottomSheetDefaults.DragHandle(color = DmsTheme.colorScheme.onSurface) }, - sheetSwipeEnabled: Boolean = true, - topBar: @Composable (() -> Unit)? = null, - snackbarHost: @Composable (SnackbarHostState) -> Unit = { SnackbarHost(it) }, - containerColor: Color = DmsTheme.colorScheme.background, - contentColor: Color = DmsTheme.colorScheme.onBackground, - content: @Composable (PaddingValues) -> Unit, -) = BottomSheetScaffold( - sheetContent = sheetContent, - modifier = modifier, - scaffoldState = scaffoldState, - sheetPeekHeight = sheetPeekHeight, - sheetShape = sheetShape, - sheetContainerColor = sheetContainerColor, - sheetContentColor = sheetContentColor, - sheetTonalElevation = sheetTonalElevation, - sheetShadowElevation = sheetShadowElevation, - sheetDragHandle = sheetDragHandle, - sheetSwipeEnabled = sheetSwipeEnabled, - topBar = topBar, - snackbarHost = snackbarHost, - containerColor = containerColor, - contentColor = contentColor, - content = content, -) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/editpassword/1_ConfirmPasswordScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/editpassword/1_ConfirmPasswordScreen.kt index 37e684e56..6e7f2a738 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/editpassword/1_ConfirmPasswordScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/editpassword/1_ConfirmPasswordScreen.kt @@ -20,7 +20,7 @@ import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.LocalToast import team.aliens.dms.android.core.ui.Banner @@ -63,7 +63,7 @@ internal fun ConfirmPasswordScreen( } } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/editpassword/2_SetPasswordScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/editpassword/2_SetPasswordScreen.kt index 66e77e63a..bdd2b798a 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/editpassword/2_SetPasswordScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/editpassword/2_SetPasswordScreen.kt @@ -25,7 +25,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.AlertDialog import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.LocalToast @@ -104,7 +104,7 @@ internal fun EditPasswordSetPasswordScreen( } } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/Main.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/Main.kt index ec13633b4..3b3bf711c 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/Main.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/Main.kt @@ -37,7 +37,7 @@ import androidx.navigation.compose.currentBackStackEntryAsState import androidx.navigation.compose.rememberNavController import com.ramcosta.composedestinations.annotation.Destination import com.ramcosta.composedestinations.annotation.RootNavGraph -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.R import team.aliens.dms.android.core.designsystem.slideInFromEnd @@ -60,7 +60,7 @@ internal fun Main( ) { val navController = rememberNavController() val (isBottomAppBarVisible, onChangeBottomAppBarVisibility) = remember { mutableStateOf(true) } - DmsScaffold( + Scaffold( modifier = modifier, bottomBar = { AnimatedVisibility( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/announcement/AnnouncementListScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/announcement/AnnouncementListScreen.kt index 53cc644bb..e3734d334 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/announcement/AnnouncementListScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/announcement/AnnouncementListScreen.kt @@ -23,7 +23,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import org.threeten.bp.LocalDateTime import team.aliens.dms.android.core.designsystem.ButtonDefaults -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.OutlinedButton @@ -61,7 +61,7 @@ internal fun AnnouncementListScreen( ) } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar(title = { Text(text = stringResource(id = R.string.announcement)) }) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt index c64b92ada..2a0e7c06e 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt @@ -26,7 +26,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.RoundedButton @@ -50,7 +50,7 @@ internal fun ApplicationScreen( val viewModel: ApplicationViewModel = hiltViewModel() val uiState by viewModel.stateFlow.collectAsStateWithLifecycle() - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar(title = { Text(text = stringResource(id = R.string.application)) }) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/home/HomeScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/home/HomeScreen.kt index 645ef9346..7fb7c62fc 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/home/HomeScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/home/HomeScreen.kt @@ -64,7 +64,7 @@ import org.threeten.bp.DayOfWeek import org.threeten.bp.LocalDate import team.aliens.dms.android.core.designsystem.ButtonDefaults import team.aliens.dms.android.core.designsystem.DmsCalendar -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.ModalBottomSheet @@ -134,7 +134,7 @@ internal fun HomeScreen( } } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt index 4f140c277..27111c0b3 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt @@ -43,7 +43,7 @@ import coil.compose.rememberAsyncImagePainter import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.AlertDialog import team.aliens.dms.android.core.designsystem.ButtonDefaults -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.Gray10 @@ -134,7 +134,7 @@ internal fun MyPageScreen( } } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/notice/NoticeDetailsScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/notice/NoticeDetailsScreen.kt index a60859a57..efd483064 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/notice/NoticeDetailsScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/notice/NoticeDetailsScreen.kt @@ -23,7 +23,7 @@ import androidx.compose.ui.unit.dp import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.VerticallyFadedColumn @@ -50,7 +50,7 @@ internal fun NoticeDetailsScreen( viewModel.postIntent(NoticeDetailsIntent.FetchNoticeDetails(noticeId)) } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt index 4cb934aae..3563bc073 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt @@ -23,7 +23,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.ButtonDefaults import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.OutlinedButton @@ -52,7 +52,7 @@ internal fun PointHistoryScreen( val viewModel: PointHistoryViewModel = hiltViewModel() val uiState by viewModel.stateFlow.collectAsStateWithLifecycle() - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/remains/RemainsApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/remains/RemainsApplicationScreen.kt index ed487b9a5..60d324c3a 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/remains/RemainsApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/remains/RemainsApplicationScreen.kt @@ -35,7 +35,7 @@ import com.ramcosta.composedestinations.annotation.Destination import org.threeten.bp.DayOfWeek import team.aliens.dms.android.core.designsystem.ButtonDefaults import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.RoundedButton @@ -64,7 +64,7 @@ internal fun RemainsApplicationScreen( val viewModel: RemainsApplicationViewModel = hiltViewModel() val uiState by viewModel.stateFlow.collectAsStateWithLifecycle() - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/signin/SignInScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/signin/SignInScreen.kt index 14d06c31e..29ee1147f 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/signin/SignInScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/signin/SignInScreen.kt @@ -15,7 +15,6 @@ import androidx.compose.foundation.text.KeyboardOptions import androidx.compose.foundation.verticalScroll import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ProvideTextStyle -import androidx.compose.material3.Scaffold import androidx.compose.material3.Text import androidx.compose.material3.TopAppBarDefaults import androidx.compose.material3.VerticalDivider @@ -41,7 +40,7 @@ import com.ramcosta.composedestinations.annotation.Destination import kotlinx.coroutines.delay import kotlinx.coroutines.launch import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.LocalToast @@ -86,7 +85,7 @@ internal fun SignInScreen( } } - DmsScaffold( + Scaffold( modifier = modifier.fillMaxSize(), topBar = { DmsTopAppBar( @@ -291,7 +290,7 @@ private fun SignInPreview() { } } - Scaffold { padValues -> + androidx.compose.material3.Scaffold { padValues -> Column( modifier = Modifier .background(DmsTheme.colorScheme.background) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/signup/1_EnterSchoolVerificationCodeScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/signup/1_EnterSchoolVerificationCodeScreen.kt index e103e98a3..e25a72aad 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/signup/1_EnterSchoolVerificationCodeScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/signup/1_EnterSchoolVerificationCodeScreen.kt @@ -19,7 +19,7 @@ import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.LocalToast import team.aliens.dms.android.core.designsystem.VerificationCodeInput @@ -58,7 +58,7 @@ internal fun EnterSchoolVerificationCodeScreen( } } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/signup/2_EnterSchoolVerificationQuestionScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/signup/2_EnterSchoolVerificationQuestionScreen.kt index c1a4a6d38..cff899730 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/signup/2_EnterSchoolVerificationQuestionScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/signup/2_EnterSchoolVerificationQuestionScreen.kt @@ -20,7 +20,7 @@ import androidx.compose.ui.res.stringResource import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.LocalToast import team.aliens.dms.android.core.designsystem.TextField @@ -59,7 +59,7 @@ internal fun EnterSchoolVerificationQuestionScreen( } } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/signup/3_EnterEmailScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/signup/3_EnterEmailScreen.kt index 0b8bc0df2..abab61c5f 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/signup/3_EnterEmailScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/signup/3_EnterEmailScreen.kt @@ -25,7 +25,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.AlertDialog import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.LocalToast import team.aliens.dms.android.core.designsystem.TextButton @@ -111,7 +111,7 @@ internal fun EnterEmailScreen( } } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/signup/4_EnterEmailVerificationCodeScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/signup/4_EnterEmailVerificationCodeScreen.kt index 5ca9cf11d..488648c35 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/signup/4_EnterEmailVerificationCodeScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/signup/4_EnterEmailVerificationCodeScreen.kt @@ -1,7 +1,6 @@ package team.aliens.dms.android.feature.signup import android.os.CountDownTimer -import androidx.activity.compose.BackHandler import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -28,7 +27,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.ButtonDefaults import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.LocalToast @@ -115,7 +114,7 @@ internal fun SignUpEnterEmailVerificationCodeScreen( } } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/signup/5_SetIdScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/signup/5_SetIdScreen.kt index a7ad60743..0fe8a8920 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/signup/5_SetIdScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/signup/5_SetIdScreen.kt @@ -33,7 +33,7 @@ import com.ramcosta.composedestinations.annotation.Destination import kotlinx.coroutines.delay import team.aliens.dms.android.core.designsystem.AlertDialog import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.LocalToast @@ -126,7 +126,7 @@ internal fun SetIdScreen( } } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/signup/6_SetPasswordScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/signup/6_SetPasswordScreen.kt index 8841cb804..ec2102cc1 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/signup/6_SetPasswordScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/signup/6_SetPasswordScreen.kt @@ -24,7 +24,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.AlertDialog import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.LocalToast import team.aliens.dms.android.core.designsystem.TextButton @@ -95,7 +95,7 @@ internal fun SignUpSetPasswordScreen( } } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/signup/8_TermsScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/signup/8_TermsScreen.kt index acee5b288..b3df8e198 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/signup/8_TermsScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/signup/8_TermsScreen.kt @@ -27,7 +27,7 @@ import androidx.compose.ui.viewinterop.AndroidView import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.Checkbox import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.LocalToast @@ -71,7 +71,7 @@ internal fun TermsScreen( } } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/studyroom/details/StudyRoomDetailsScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/studyroom/details/StudyRoomDetailsScreen.kt index 4eabe0c3a..2097014c8 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/studyroom/details/StudyRoomDetailsScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/studyroom/details/StudyRoomDetailsScreen.kt @@ -48,7 +48,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.Button import team.aliens.dms.android.core.designsystem.ButtonDefaults -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.ShadowDefaults @@ -91,7 +91,7 @@ internal fun StudyRoomDetailsScreen( ) } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/studyroom/list/StudyRoomListScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/studyroom/list/StudyRoomListScreen.kt index 8d2d0d1a1..ab043896f 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/studyroom/list/StudyRoomListScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/studyroom/list/StudyRoomListScreen.kt @@ -30,7 +30,7 @@ import com.ramcosta.composedestinations.annotation.Destination import kotlinx.coroutines.launch import team.aliens.dms.android.core.designsystem.Button import team.aliens.dms.android.core.designsystem.ButtonDefaults -import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.ModalBottomSheet @@ -140,7 +140,7 @@ internal fun StudyRoomListScreen( } } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( From dd4dfac6115ab182bcbd28168c98dc0e6a6de1be Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 20:50:44 +0900 Subject: [PATCH 047/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20scre?= =?UTF-8?q?en?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/outing/OutingApplicationScreen.kt | 10 ++++++++++ .../feature/outing/OutingStatusScreen.kt | 20 +++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt create mode 100644 feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt new file mode 100644 index 000000000..95e1873e5 --- /dev/null +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt @@ -0,0 +1,10 @@ +package team.aliens.dms.android.feature.outing + +import androidx.compose.runtime.Composable +import com.ramcosta.composedestinations.annotation.Destination + +@Composable +@Destination +fun OutingApplicationScreen() { + +} diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt new file mode 100644 index 000000000..d4696beff --- /dev/null +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt @@ -0,0 +1,20 @@ +package team.aliens.dms.android.feature.outing + +import androidx.compose.runtime.Composable +import androidx.hilt.navigation.compose.hiltViewModel +import com.ramcosta.composedestinations.annotation.Destination +import team.aliens.dms.android.core.designsystem.Scaffold +import team.aliens.dms.android.feature.outing.navigation.OutingNavigator + +@Destination +@Composable +fun OutingStatusScreen( + navigator: OutingNavigator, + viewModel: OutingViewModel = hiltViewModel(), +) { + Scaffold( + + ) { padValues -> + + } +} From a2f900cf74d0bcaa0d06eb1dd1265510b0cc5ea4 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 20:50:48 +0900 Subject: [PATCH 048/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20viewmodel?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/outing/OutingViewModel.kt | 35 +++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt new file mode 100644 index 000000000..4d2e57566 --- /dev/null +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt @@ -0,0 +1,35 @@ +package team.aliens.dms.android.feature.outing + +import dagger.hilt.android.lifecycle.HiltViewModel +import team.aliens.dms.android.core.ui.mvi.BaseMviViewModel +import team.aliens.dms.android.core.ui.mvi.Intent +import team.aliens.dms.android.core.ui.mvi.SideEffect +import team.aliens.dms.android.core.ui.mvi.UiState +import team.aliens.dms.android.data.outing.model.OutingApplicationTime +import team.aliens.dms.android.data.outing.repository.OutingRepository +import javax.inject.Inject + +@HiltViewModel +class OutingViewModel @Inject constructor( + private val outingRepository: OutingRepository, +) : BaseMviViewModel( + initialState = OutingUiState.initial(), +) { + override fun processIntent(intent: OutingIntent) { + + } +} + +data class OutingUiState( + val outingApplicationTime: OutingApplicationTime?, +) : UiState() { + companion object { + fun initial() = OutingUiState( + outingApplicationTime = null, + ) + } +} + +sealed class OutingIntent : Intent() + +sealed class OutingSideEffect : SideEffect() From aad3f42ca40d702ff47ca570cd6b807f445b1682 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 21:50:43 +0900 Subject: [PATCH 049/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20navigator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/outing/navigation/OutingNavigator.kt | 6 ++++++ 1 file changed, 6 insertions(+) create mode 100644 feature/src/main/java/team/aliens/dms/android/feature/outing/navigation/OutingNavigator.kt diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/navigation/OutingNavigator.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/navigation/OutingNavigator.kt new file mode 100644 index 000000000..f01041e58 --- /dev/null +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/navigation/OutingNavigator.kt @@ -0,0 +1,6 @@ +package team.aliens.dms.android.feature.outing.navigation + +interface OutingNavigator { + fun openOutingApplication() + fun navigateUp() +} From 17141f49f447b1f6e1d3c32b489d0f39b65071d2 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 21:50:48 +0900 Subject: [PATCH 050/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20authorized?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/app/navigation/authorized/AuthorizedNavigator.kt | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/team/aliens/dms/android/app/navigation/authorized/AuthorizedNavigator.kt b/app/src/main/java/team/aliens/dms/android/app/navigation/authorized/AuthorizedNavigator.kt index 11aa50e78..7e113dc17 100644 --- a/app/src/main/java/team/aliens/dms/android/app/navigation/authorized/AuthorizedNavigator.kt +++ b/app/src/main/java/team/aliens/dms/android/app/navigation/authorized/AuthorizedNavigator.kt @@ -5,6 +5,7 @@ import team.aliens.dms.android.feature.editprofile.navigation.EditProfileNavigat import team.aliens.dms.android.feature.main.navigation.MainNavigator import team.aliens.dms.android.feature.notice.navigation.NoticeNavigator import team.aliens.dms.android.feature.notification.navigation.NotificationNavigation +import team.aliens.dms.android.feature.outing.navigation.OutingNavigator import team.aliens.dms.android.feature.point.navigation.PointHistoryNavigator import team.aliens.dms.android.feature.remains.navigator.RemainsNavigator import team.aliens.dms.android.feature.studyroom.navigation.StudyRoomNavigator @@ -17,4 +18,5 @@ interface AuthorizedNavigator : NotificationNavigation, PointHistoryNavigator, RemainsNavigator, - StudyRoomNavigator + StudyRoomNavigator, + OutingNavigator From 72ca5d0523bdc8eeeb2d5d0da88941773c535d42 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 21:50:52 +0900 Subject: [PATCH 051/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20dms=20app?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/team/aliens/dms/android/app/DmsApp.kt | 9 +++++++++ .../aliens/dms/android/app/navigation/DmsNavigator.kt | 5 +++++ 2 files changed, 14 insertions(+) diff --git a/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt b/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt index 576569bcd..73a65ba4a 100644 --- a/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt +++ b/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt @@ -19,6 +19,8 @@ import team.aliens.dms.android.app.navigation.DmsNavigator import team.aliens.dms.android.feature.destinations.TermsScreenDestination import team.aliens.dms.android.feature.editpassword.EditPasswordViewModel import team.aliens.dms.android.feature.editpassword.navigation.EditPasswordNavGraph +import team.aliens.dms.android.feature.outing.OutingViewModel +import team.aliens.dms.android.feature.outing.navigation.OutingNavGraph import team.aliens.dms.android.feature.signup.SignUpViewModel import team.aliens.dms.android.feature.signup.TermsUrl import team.aliens.dms.android.feature.signup.navigation.SignUpNavGraph @@ -55,6 +57,13 @@ fun DmsApp( } hiltViewModel(parentEntry) } + + dependency(OutingNavGraph) { + val parentEntry = remember(navBackStackEntry) { + navController.getBackStackEntry(OutingNavGraph.route) + } + hiltViewModel(parentEntry) + } }, ) } diff --git a/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt b/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt index 31ab6655f..db62de8d5 100644 --- a/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt +++ b/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt @@ -34,6 +34,7 @@ import team.aliens.dms.android.feature.destinations.StudyRoomDetailsScreenDestin import team.aliens.dms.android.feature.destinations.StudyRoomListScreenDestination import team.aliens.dms.android.feature.destinations.TermsScreenDestination import team.aliens.dms.android.feature.editpassword.navigation.EditPasswordNavGraph +import team.aliens.dms.android.feature.outing.navigation.OutingNavGraph import team.aliens.dms.android.feature.resetpassword.navigation.ResetPasswordNavGraph import team.aliens.dms.android.feature.signup.navigation.SignUpNavGraph import java.util.UUID @@ -217,6 +218,10 @@ class DmsNavigator( ) within navGraph, ) } + + override fun openOutingApplication() { + navController.navigateSingleTop(OutingNavGraph within AuthorizedNavGraph) + } } private fun NavController.navigateSingleTop( From 75a6435827f1d201f74c52a2b3d87e3c33198e5d Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 23:01:16 +0900 Subject: [PATCH 052/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20dms=20nav?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/aliens/dms/android/app/navigation/DmsNavigator.kt | 6 ++++++ .../dms/android/feature/main/navigation/MainNavigator.kt | 2 ++ 2 files changed, 8 insertions(+) diff --git a/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt b/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt index db62de8d5..e005a0432 100644 --- a/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt +++ b/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt @@ -82,6 +82,12 @@ class DmsNavigator( navController.navigateSingleTop(NoticeDetailsScreenDestination(noticeId) within navGraph) } + override fun openOutingNav() { + navController.navigateSingleTop(OutingNavGraph) { + restoreState = true + } + } + override fun openEditPasswordSetPassword(currentPassword: String) { navController.navigateSingleTop(EditPasswordSetPasswordScreenDestination within EditPasswordNavGraph) } diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/navigation/MainNavigator.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/navigation/MainNavigator.kt index f81797e5c..8011ff151 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/navigation/MainNavigator.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/navigation/MainNavigator.kt @@ -19,4 +19,6 @@ interface MainNavigator { fun openEditPasswordNav() fun openNoticeDetails(noticeId: UUID) + + fun openOutingNav() } From 5e7a1000c8889245ab757a865a6bd2ec6f2a3900 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 23:01:23 +0900 Subject: [PATCH 053/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20dms=20main?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/java/team/aliens/dms/android/feature/main/Main.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/Main.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/Main.kt index 3b3bf711c..20a2da500 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/Main.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/Main.kt @@ -120,8 +120,9 @@ internal fun Main( }, ) { ApplicationScreen( - onNavigateToStudyRoomList = { mainNavigator.openStudyRoomList() }, - onNavigateToRemains = { mainNavigator.openRemainsApplication() }, + onNavigateToStudyRoomList = mainNavigator::openStudyRoomList, + onNavigateToRemains = mainNavigator::openRemainsApplication, + onNavigateToOuting = mainNavigator::openOutingNav, ) } From 1c7e26f8f1525c5e3c4635f0a687004659ae190e Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 23:01:28 +0900 Subject: [PATCH 054/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20application?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/application/ApplicationScreen.kt | 17 +++++++++++++---- .../studyroom/list/StudyRoomListScreen.kt | 2 +- 2 files changed, 14 insertions(+), 5 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt index 2a0e7c06e..7b4607f9c 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt @@ -26,10 +26,10 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.RoundedButton +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.ShadowDefaults import team.aliens.dms.android.core.ui.DefaultVerticalSpace import team.aliens.dms.android.core.ui.PaddingDefaults @@ -46,6 +46,7 @@ internal fun ApplicationScreen( modifier: Modifier = Modifier, onNavigateToStudyRoomList: () -> Unit, onNavigateToRemains: () -> Unit, + onNavigateToOuting: () -> Unit, ) { val viewModel: ApplicationViewModel = hiltViewModel() val uiState by viewModel.stateFlow.collectAsStateWithLifecycle() @@ -65,7 +66,7 @@ internal fun ApplicationScreen( modifier = Modifier .fillMaxWidth() .topPadding(), - title = stringResource(id = R.string.study_room), + title = stringResource(id = R.string.study_room_application), appliedTitle = uiState.appliedStudyRoom?.let { studyRoom -> stringResource( id = R.string.format_study_room_applied_text, @@ -74,17 +75,25 @@ internal fun ApplicationScreen( ) }, description = stringResource(id = R.string.study_room_description), - buttonText = stringResource(id = R.string.study_room_application), + buttonText = stringResource(id = R.string.study_room_do_application), onButtonClick = onNavigateToStudyRoomList, ) ApplicationCard( modifier = Modifier.fillMaxWidth(), - title = stringResource(id = R.string.remains_do_application), + title = stringResource(id = R.string.remains_application), appliedTitle = uiState.appliedRemainsOption?.title, description = stringResource(id = R.string.remains_description), buttonText = stringResource(id = R.string.remains_do_application), onButtonClick = onNavigateToRemains, ) + ApplicationCard( + modifier = Modifier.fillMaxWidth(), + title = stringResource(id = R.string.outing_application), + appliedTitle = uiState.appliedRemainsOption?.title, + description = stringResource(id = R.string.outing_description), + buttonText = stringResource(id = R.string.outing_do_application), + onButtonClick = onNavigateToOuting, + ) } } } diff --git a/feature/src/main/java/team/aliens/dms/android/feature/studyroom/list/StudyRoomListScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/studyroom/list/StudyRoomListScreen.kt index ab043896f..1ee5aa81c 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/studyroom/list/StudyRoomListScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/studyroom/list/StudyRoomListScreen.kt @@ -153,7 +153,7 @@ internal fun StudyRoomListScreen( } }, title = { - Text(text = stringResource(id = R.string.study_room_application)) + Text(text = stringResource(id = R.string.study_room_do_application)) }, ) }, From 274e1d7cbedb447a1df0784c1c135b7b432c6250 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 17 Mar 2024 23:01:43 +0900 Subject: [PATCH 055/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/outing/OutingStatusScreen.kt | 41 ++++++++++++++++++- .../android/feature/outing/OutingViewModel.kt | 6 ++- feature/src/main/res/values/strings.xml | 7 +++- 3 files changed, 50 insertions(+), 4 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt index d4696beff..10f5ce3bd 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt @@ -1,20 +1,59 @@ package team.aliens.dms.android.feature.outing +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.getValue +import androidx.compose.ui.Modifier +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination +import team.aliens.dms.android.core.designsystem.DmsTheme +import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.Scaffold +import team.aliens.dms.android.feature.R import team.aliens.dms.android.feature.outing.navigation.OutingNavigator +@OptIn(ExperimentalMaterial3Api::class) @Destination @Composable fun OutingStatusScreen( navigator: OutingNavigator, viewModel: OutingViewModel = hiltViewModel(), ) { - Scaffold( + val uiState by viewModel.stateFlow.collectAsStateWithLifecycle() + Scaffold( + topBar = { + DmsTopAppBar( + title = { Text(text = stringResource(id = R.string.outing_application)) }, + navigationIcon = { + IconButton(onClick = navigator::navigateUp) { + Icon( + painter = painterResource(id = R.drawable.ic_baseline_arrow_back_24), + contentDescription = stringResource(id = R.string.top_bar_back_button), + ) + } + }, + ) + }, ) { padValues -> + Column( + modifier = Modifier.fillMaxSize(), + ) { + Text( + modifier = Modifier.fillMaxWidth(), + text = stringResource(id = R.string.outing_recent_application), + color = DmsTheme.colorScheme.surfaceVariant, + ) + } } } diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt index 4d2e57566..011321ce1 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt @@ -5,6 +5,7 @@ import team.aliens.dms.android.core.ui.mvi.BaseMviViewModel import team.aliens.dms.android.core.ui.mvi.Intent import team.aliens.dms.android.core.ui.mvi.SideEffect import team.aliens.dms.android.core.ui.mvi.UiState +import team.aliens.dms.android.data.outing.model.CurrentAppliedOutingApplication import team.aliens.dms.android.data.outing.model.OutingApplicationTime import team.aliens.dms.android.data.outing.repository.OutingRepository import javax.inject.Inject @@ -21,11 +22,12 @@ class OutingViewModel @Inject constructor( } data class OutingUiState( - val outingApplicationTime: OutingApplicationTime?, + // val outingApplicationTime: List?, + val currentAppliedOutingApplication: CurrentAppliedOutingApplication?, ) : UiState() { companion object { fun initial() = OutingUiState( - outingApplicationTime = null, + currentAppliedOutingApplication = null, ) } } diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index 91b8a702f..d3c473770 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -233,7 +233,8 @@ 시간 자습실 - 자습실 신청하기 + 자습실 신청 + 자습실 신청하기 %d층 %s 자습실 신청 시간은 %s ~ %s 입니다 @@ -290,4 +291,8 @@ 외출 신청 + 외출 신청 시간은 %s ~ %s 입니다 + 신청 내역 + 외출 신청하기 + 기숙사에서 생활하는 동안 밖에 다녀올 일이 있다면 외출을 신청해 보세요. \ No newline at end of file From cebe12a47f9ca1645dbc4fadc692660c0d87fc80 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Mon, 18 Mar 2024 11:41:25 +0900 Subject: [PATCH 056/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20shadow?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/aliens/dms/android/core/designsystem/Shadows.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Shadows.kt b/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Shadows.kt index 41a8d7613..48ff45cf3 100644 --- a/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Shadows.kt +++ b/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Shadows.kt @@ -26,9 +26,9 @@ fun Modifier.shadow( } object ShadowDefaults { - val SmallElevation = 4.dp - val MediumElevation = 8.dp - val LargeElevation = 12.dp + val SmallElevation = 2.dp + val MediumElevation = 4.dp + val LargeElevation = 8.dp val RoundedShape = RoundedCornerShape(8.dp) } From 0d7cb42d92f2fa01e58bcd1a23d3e416591c64b0 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Mon, 18 Mar 2024 12:05:40 +0900 Subject: [PATCH 057/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20shape?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/outing/OutingStatusScreen.kt | 148 +++++++++++++++++- 1 file changed, 145 insertions(+), 3 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt index 10f5ce3bd..72625e784 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt @@ -1,25 +1,48 @@ package team.aliens.dms.android.feature.outing +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.lazy.LazyRow +import androidx.compose.foundation.lazy.itemsIndexed +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +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.font.FontWeight import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination +import org.threeten.bp.LocalDate +import team.aliens.dms.android.core.designsystem.ButtonDefaults import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.Scaffold +import team.aliens.dms.android.core.designsystem.ShadowDefaults +import team.aliens.dms.android.core.designsystem.TextButton +import team.aliens.dms.android.core.ui.DefaultHorizontalSpace +import team.aliens.dms.android.core.ui.DefaultVerticalSpace +import team.aliens.dms.android.core.ui.PaddingDefaults +import team.aliens.dms.android.core.ui.bottomPadding +import team.aliens.dms.android.core.ui.horizontalPadding +import team.aliens.dms.android.core.ui.startPadding +import team.aliens.dms.android.core.ui.topPadding +import team.aliens.dms.android.core.ui.verticalPadding import team.aliens.dms.android.feature.R import team.aliens.dms.android.feature.outing.navigation.OutingNavigator +import team.aliens.dms.android.shared.date.util.now +import java.util.UUID @OptIn(ExperimentalMaterial3Api::class) @Destination @@ -46,14 +69,133 @@ fun OutingStatusScreen( }, ) { padValues -> Column( - modifier = Modifier.fillMaxSize(), + modifier = Modifier + .fillMaxSize() + .padding(padValues), ) { Text( - modifier = Modifier.fillMaxWidth(), + modifier = Modifier + .fillMaxWidth() + .startPadding() + .topPadding(), text = stringResource(id = R.string.outing_recent_application), - color = DmsTheme.colorScheme.surfaceVariant, + color = DmsTheme.colorScheme.icon, ) + OutingInformationCard( + outingId = UUID.randomUUID(), + title = "어쩌구", + date = now.toLocalDate(), + time = "22:40~25:50", + companionNames = listOf("박준수", "벅즁수", "박박수", "준박수"), + reason = "배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서", + ) {} + } + } +} + +@Composable +private fun OutingInformationCard( + modifier: Modifier = Modifier, + outingId: UUID, + title: String, + date: LocalDate, + time: String, + companionNames: List, + reason: String?, + onCancelApplication: (id: UUID) -> Unit, +) { + Card( + modifier = modifier + .horizontalPadding() + .verticalPadding(PaddingDefaults.ExtraSmall), + shape = DmsTheme.shapes.surfaceMedium, + colors = CardDefaults.cardColors( + containerColor = DmsTheme.colorScheme.surface, + contentColor = DmsTheme.colorScheme.onSurface, + ), + elevation = CardDefaults.outlinedCardElevation(defaultElevation = ShadowDefaults.SmallElevation), + ) { + Column( + modifier = Modifier.fillMaxWidth(), + verticalArrangement = Arrangement.spacedBy(DefaultVerticalSpace), + ) { + Row( + modifier = Modifier + .fillMaxWidth() + .horizontalPadding() + .topPadding(), + horizontalArrangement = Arrangement.SpaceBetween, + verticalAlignment = Alignment.CenterVertically, + ) { + // TODO + Text( + text = date.toString(), + style = DmsTheme.typography.caption, + color = DmsTheme.colorScheme.primary, + ) + TextButton( + onClick = { onCancelApplication(outingId) }, + colors = ButtonDefaults.textErrorButtonColors(), + ) { + Text(text = stringResource(id = R.string.outing_cancel_application)) + } + } + Text( + modifier = Modifier.startPadding(), + text = title, + style = DmsTheme.typography.title3, + fontWeight = FontWeight.Bold, + ) + Text( + modifier = Modifier.startPadding(), + text = time, + style = DmsTheme.typography.body2, + ) + if (companionNames.isNotEmpty()) { + LazyRow( + verticalAlignment = Alignment.CenterVertically, + horizontalArrangement = Arrangement.spacedBy(DefaultHorizontalSpace), + ) { + item { + Text( + modifier = Modifier.startPadding(), + text = stringResource(id = R.string.outing_companion_names), + style = DmsTheme.typography.body2, + fontWeight = FontWeight.Bold, + ) + } + itemsIndexed(companionNames) { index, name -> + Text( + text = if (index == companionNames.lastIndex) { + name + } else { + "$name, " + }, + style = DmsTheme.typography.body2, + ) + } + } + } + if (reason != null) { + Card( + modifier = Modifier + .fillMaxWidth() + .horizontalPadding() + .bottomPadding(), + colors = CardDefaults.cardColors( + containerColor = DmsTheme.colorScheme.background, + contentColor = DmsTheme.colorScheme.onBackground, + ), + ) { + Text( + modifier = Modifier + .horizontalPadding() + .verticalPadding(), + text = reason, + ) + } + } } } } From 37445d2bb424d60abf0afb58b6ba18043b29564a Mon Sep 17 00:00:00 2001 From: junsuPark Date: Mon, 18 Mar 2024 12:11:50 +0900 Subject: [PATCH 058/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20application?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/outing/OutingStatusScreen.kt | 34 +++++++++++++++++-- feature/src/main/res/values/strings.xml | 3 ++ 2 files changed, 34 insertions(+), 3 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt index 72625e784..feb29e50a 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt @@ -16,6 +16,8 @@ import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource @@ -25,6 +27,7 @@ import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import org.threeten.bp.LocalDate +import team.aliens.dms.android.core.designsystem.AlertDialog import team.aliens.dms.android.core.designsystem.ButtonDefaults import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar @@ -52,6 +55,30 @@ fun OutingStatusScreen( viewModel: OutingViewModel = hiltViewModel(), ) { val uiState by viewModel.stateFlow.collectAsStateWithLifecycle() + val (shouldShowCancelOutingApplicationDialog, onChangeShouldShowCancelOutingDialog) = remember { + mutableStateOf(false) + } + if (shouldShowCancelOutingApplicationDialog) { + AlertDialog( + title = { Text(text = stringResource(id = R.string.outing_cancel_application)) }, + text = { Text(text = stringResource(id = R.string.outing_are_you_sure_you_cancel_application)) }, + onDismissRequest = { onChangeShouldShowCancelOutingDialog(false) }, + confirmButton = { + TextButton( + onClick = { viewModel.postIntent(OutingIntent.CancelCurrentApplication) }, + ) { + Text(text = stringResource(id = R.string.accept)) + } + }, + dismissButton = { + TextButton( + onClick = { onChangeShouldShowCancelOutingDialog(false) }, + ) { + Text(text = stringResource(id = R.string.cancel)) + } + }, + ) + } Scaffold( topBar = { @@ -88,7 +115,8 @@ fun OutingStatusScreen( time = "22:40~25:50", companionNames = listOf("박준수", "벅즁수", "박박수", "준박수"), reason = "배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서", - ) {} + onCancelApplication = { onChangeShouldShowCancelOutingDialog(true) } + ) } } } @@ -102,7 +130,7 @@ private fun OutingInformationCard( time: String, companionNames: List, reason: String?, - onCancelApplication: (id: UUID) -> Unit, + onCancelApplication: () -> Unit, ) { Card( @@ -135,7 +163,7 @@ private fun OutingInformationCard( color = DmsTheme.colorScheme.primary, ) TextButton( - onClick = { onCancelApplication(outingId) }, + onClick = onCancelApplication, colors = ButtonDefaults.textErrorButtonColors(), ) { Text(text = stringResource(id = R.string.outing_cancel_application)) diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index d3c473770..1180c4bcf 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -295,4 +295,7 @@ 신청 내역 외출 신청하기 기숙사에서 생활하는 동안 밖에 다녀올 일이 있다면 외출을 신청해 보세요. + 신청 취소 + 동행자: + 작성한 정보가 파기됩니다. 계속하시겠습니까? \ No newline at end of file From fdb1bee82b65dcc0560e8465197328be9bb9b03a Mon Sep 17 00:00:00 2001 From: junsuPark Date: Mon, 18 Mar 2024 12:53:51 +0900 Subject: [PATCH 059/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/outing/OutingStatusScreen.kt | 74 ++++++++++++++----- .../android/feature/outing/OutingViewModel.kt | 38 +++++++++- feature/src/main/res/values/strings.xml | 2 + 3 files changed, 91 insertions(+), 23 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt index feb29e50a..5472a2b1a 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt @@ -1,6 +1,7 @@ package team.aliens.dms.android.feature.outing import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.fillMaxSize @@ -20,6 +21,7 @@ import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight @@ -28,9 +30,11 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import org.threeten.bp.LocalDate import team.aliens.dms.android.core.designsystem.AlertDialog +import team.aliens.dms.android.core.designsystem.Button import team.aliens.dms.android.core.designsystem.ButtonDefaults import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar +import team.aliens.dms.android.core.designsystem.LocalToast import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.ShadowDefaults import team.aliens.dms.android.core.designsystem.TextButton @@ -38,13 +42,13 @@ import team.aliens.dms.android.core.ui.DefaultHorizontalSpace import team.aliens.dms.android.core.ui.DefaultVerticalSpace import team.aliens.dms.android.core.ui.PaddingDefaults import team.aliens.dms.android.core.ui.bottomPadding +import team.aliens.dms.android.core.ui.collectInLaunchedEffectWithLifecycle import team.aliens.dms.android.core.ui.horizontalPadding import team.aliens.dms.android.core.ui.startPadding import team.aliens.dms.android.core.ui.topPadding import team.aliens.dms.android.core.ui.verticalPadding import team.aliens.dms.android.feature.R import team.aliens.dms.android.feature.outing.navigation.OutingNavigator -import team.aliens.dms.android.shared.date.util.now import java.util.UUID @OptIn(ExperimentalMaterial3Api::class) @@ -58,6 +62,8 @@ fun OutingStatusScreen( val (shouldShowCancelOutingApplicationDialog, onChangeShouldShowCancelOutingDialog) = remember { mutableStateOf(false) } + val toast = LocalToast.current + val context = LocalContext.current if (shouldShowCancelOutingApplicationDialog) { AlertDialog( title = { Text(text = stringResource(id = R.string.outing_cancel_application)) }, @@ -80,6 +86,14 @@ fun OutingStatusScreen( ) } + viewModel.sideEffectFlow.collectInLaunchedEffectWithLifecycle { sideEffect -> + when (sideEffect) { + OutingSideEffect.CurrentAppliedOutingApplicationNotFound -> toast.showErrorToast( + message = context.getString(R.string.outing_failed_to_fetch_current_applied_outing_application), + ) + } + } + Scaffold( topBar = { DmsTopAppBar( @@ -95,28 +109,50 @@ fun OutingStatusScreen( ) }, ) { padValues -> - Column( + Box( modifier = Modifier .fillMaxSize() .padding(padValues), + contentAlignment = Alignment.BottomCenter, ) { - Text( - modifier = Modifier - .fillMaxWidth() - .startPadding() - .topPadding(), - text = stringResource(id = R.string.outing_recent_application), - color = DmsTheme.colorScheme.icon, - ) - OutingInformationCard( - outingId = UUID.randomUUID(), - title = "어쩌구", - date = now.toLocalDate(), - time = "22:40~25:50", - companionNames = listOf("박준수", "벅즁수", "박박수", "준박수"), - reason = "배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서배고파서", - onCancelApplication = { onChangeShouldShowCancelOutingDialog(true) } - ) + Column( + modifier = Modifier.fillMaxSize(), + verticalArrangement = Arrangement.spacedBy(DefaultVerticalSpace), + ) { + Text( + modifier = Modifier + .fillMaxWidth() + .startPadding() + .verticalPadding(), + text = stringResource(id = R.string.outing_recent_application), + color = DmsTheme.colorScheme.icon, + ) + uiState.currentAppliedOutingApplication?.let { outingApplication -> + OutingInformationCard( + outingId = UUID.randomUUID(), + title = outingApplication.type, + date = outingApplication.date, + time = stringResource( + id = R.string.outing_format_duration, + outingApplication.startTime, + outingApplication.endTime + ), + companionNames = outingApplication.companionNames, + reason = outingApplication.reason, + onCancelApplication = { onChangeShouldShowCancelOutingDialog(true) }) + } + } + if (uiState.currentAppliedOutingApplication == null) { + Button( + modifier = Modifier + .fillMaxWidth() + .bottomPadding() + .horizontalPadding(), + onClick = {}, + ) { + Text(text = stringResource(id = R.string.outing_do_application)) + } + } } } } diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt index 011321ce1..a3332edfe 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt @@ -1,12 +1,14 @@ package team.aliens.dms.android.feature.outing +import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch import team.aliens.dms.android.core.ui.mvi.BaseMviViewModel import team.aliens.dms.android.core.ui.mvi.Intent import team.aliens.dms.android.core.ui.mvi.SideEffect import team.aliens.dms.android.core.ui.mvi.UiState import team.aliens.dms.android.data.outing.model.CurrentAppliedOutingApplication -import team.aliens.dms.android.data.outing.model.OutingApplicationTime import team.aliens.dms.android.data.outing.repository.OutingRepository import javax.inject.Inject @@ -16,7 +18,31 @@ class OutingViewModel @Inject constructor( ) : BaseMviViewModel( initialState = OutingUiState.initial(), ) { + init { + fetchCurrentAppliedOutingApplication() + } + override fun processIntent(intent: OutingIntent) { + when (intent) { + is OutingIntent.CancelCurrentApplication -> cancelApplication() + } + } + + private fun fetchCurrentAppliedOutingApplication() = viewModelScope.launch(Dispatchers.IO) { + runCatching { + outingRepository.fetchCurrentAppliedOutingApplication() + }.onSuccess { fetchedOutingApplication -> + reduce( + newState = stateFlow.value.copy( + currentAppliedOutingApplication = fetchedOutingApplication, + ), + ) + }.onFailure { + postSideEffect(OutingSideEffect.CurrentAppliedOutingApplicationNotFound) + } + } + + private fun cancelApplication() = viewModelScope.launch(Dispatchers.IO) { } } @@ -27,11 +53,15 @@ data class OutingUiState( ) : UiState() { companion object { fun initial() = OutingUiState( - currentAppliedOutingApplication = null, + currentAppliedOutingApplication = null, ) } } -sealed class OutingIntent : Intent() +sealed class OutingIntent : Intent() { + data object CancelCurrentApplication : OutingIntent() +} -sealed class OutingSideEffect : SideEffect() +sealed class OutingSideEffect : SideEffect() { + data object CurrentAppliedOutingApplicationNotFound : OutingSideEffect() +} diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index 1180c4bcf..0a2a436df 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -298,4 +298,6 @@ 신청 취소 동행자: 작성한 정보가 파기됩니다. 계속하시겠습니까? + 외출 신청 정보를 조회할 수 없습니다 + %s ~ %s \ No newline at end of file From fb135c9652e7736f3664bf8a1279795c87a2330a Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 19 Mar 2024 22:08:36 +0900 Subject: [PATCH 060/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20navigator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/app/navigation/DmsNavigator.kt | 3 ++- feature/src/main/res/values/strings.xml | 17 ++++++++++++++--- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt b/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt index e005a0432..cf5275181 100644 --- a/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt +++ b/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt @@ -21,6 +21,7 @@ import team.aliens.dms.android.feature.destinations.FindIdScreenDestination import team.aliens.dms.android.feature.destinations.MainDestination import team.aliens.dms.android.feature.destinations.NoticeDetailsScreenDestination import team.aliens.dms.android.feature.destinations.NotificationBoxScreenDestination +import team.aliens.dms.android.feature.destinations.OutingApplicationScreenDestination import team.aliens.dms.android.feature.destinations.PointHistoryScreenDestination import team.aliens.dms.android.feature.destinations.RemainsApplicationScreenDestination import team.aliens.dms.android.feature.destinations.ResetPasswordEnterEmailVerificationCodeScreenDestination @@ -226,7 +227,7 @@ class DmsNavigator( } override fun openOutingApplication() { - navController.navigateSingleTop(OutingNavGraph within AuthorizedNavGraph) + navController.navigateSingleTop(OutingApplicationScreenDestination within OutingNavGraph) } } diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index 0a2a436df..99507ce89 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -12,6 +12,7 @@ 인증 확인 + 닫기 취소 동의 @@ -291,13 +292,23 @@ 외출 신청 - 외출 신청 시간은 %s ~ %s 입니다 + 외출 시간 선택 + 외출 신청 시간은 %02d:%02d ~ %02d:%02d 입니다 신청 내역 외출 신청하기 기숙사에서 생활하는 동안 밖에 다녀올 일이 있다면 외출을 신청해 보세요. 신청 취소 - 동행자: + 동행자 작성한 정보가 파기됩니다. 계속하시겠습니까? 외출 신청 정보를 조회할 수 없습니다 - %s ~ %s + %02d:%02d + 외출 유형이 존재하지 않습니다 + 선택 + 외출 유형 + 동행자 추가 + 는 필수 입력 항목입니다 + 외출 일자 + %04d.%02d.%02d (%s) + 외출 시간 + 복귀 시간 \ No newline at end of file From 3cbd34fa6f8d8889dc3245182df3c40e74a8ac90 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 19 Mar 2024 22:08:42 +0900 Subject: [PATCH 061/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20status?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/feature/outing/OutingStatusScreen.kt | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt index 5472a2b1a..92fa826c0 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt @@ -25,7 +25,6 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight -import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import org.threeten.bp.LocalDate @@ -56,7 +55,7 @@ import java.util.UUID @Composable fun OutingStatusScreen( navigator: OutingNavigator, - viewModel: OutingViewModel = hiltViewModel(), + viewModel: OutingViewModel, ) { val uiState by viewModel.stateFlow.collectAsStateWithLifecycle() val (shouldShowCancelOutingApplicationDialog, onChangeShouldShowCancelOutingDialog) = remember { @@ -133,7 +132,7 @@ fun OutingStatusScreen( title = outingApplication.type, date = outingApplication.date, time = stringResource( - id = R.string.outing_format_duration, + id = R.string.outing_format_duration_h_m, outingApplication.startTime, outingApplication.endTime ), @@ -148,7 +147,7 @@ fun OutingStatusScreen( .fillMaxWidth() .bottomPadding() .horizontalPadding(), - onClick = {}, + onClick = navigator::openOutingApplication, ) { Text(text = stringResource(id = R.string.outing_do_application)) } From b27af5ff77b7b78aabfaee4c93f21717e7392d29 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 19 Mar 2024 22:08:45 +0900 Subject: [PATCH 062/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20application?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/feature/main/application/ApplicationScreen.kt | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt index 7b4607f9c..2b6b026d1 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt @@ -89,7 +89,6 @@ internal fun ApplicationScreen( ApplicationCard( modifier = Modifier.fillMaxWidth(), title = stringResource(id = R.string.outing_application), - appliedTitle = uiState.appliedRemainsOption?.title, description = stringResource(id = R.string.outing_description), buttonText = stringResource(id = R.string.outing_do_application), onButtonClick = onNavigateToOuting, @@ -103,7 +102,7 @@ private fun ApplicationCard( modifier: Modifier = Modifier, title: String, description: String, - appliedTitle: String?, + appliedTitle: String? = null, buttonText: String, onButtonClick: () -> Unit, ) { From fb59dbd7c7e6680d8ff211c0a71ea503d53f193f Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 19 Mar 2024 22:08:52 +0900 Subject: [PATCH 063/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20appl?= =?UTF-8?q?ication=20form?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/outing/OutingApplicationScreen.kt | 369 +++++++++++++++++- .../android/feature/outing/OutingViewModel.kt | 44 ++- 2 files changed, 411 insertions(+), 2 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt index 95e1873e5..c00330e34 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt @@ -1,10 +1,377 @@ package team.aliens.dms.android.feature.outing +import androidx.compose.foundation.background +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +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.shape.CircleShape +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.ExposedDropdownMenuBox +import androidx.compose.material3.ExposedDropdownMenuDefaults +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text +import androidx.compose.material3.TimePicker +import androidx.compose.material3.rememberTimePickerState import androidx.compose.runtime.Composable +import androidx.compose.runtime.Stable +import androidx.compose.runtime.getValue +import androidx.compose.runtime.mutableStateOf +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.graphics.Color +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.unit.DpSize +import androidx.compose.ui.unit.dp +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination +import org.threeten.bp.DayOfWeek +import team.aliens.dms.android.core.designsystem.AlertDialog +import team.aliens.dms.android.core.designsystem.DmsTheme +import team.aliens.dms.android.core.designsystem.DmsTopAppBar +import team.aliens.dms.android.core.designsystem.Scaffold +import team.aliens.dms.android.core.designsystem.TextButton +import team.aliens.dms.android.core.designsystem.TextField +import team.aliens.dms.android.core.ui.DefaultHorizontalSpace +import team.aliens.dms.android.core.ui.DefaultVerticalSpace +import team.aliens.dms.android.core.ui.composable.FloatingNotice +import team.aliens.dms.android.core.ui.endPadding +import team.aliens.dms.android.core.ui.startPadding +import team.aliens.dms.android.feature.R +import team.aliens.dms.android.feature.outing.navigation.OutingNavigator +import team.aliens.dms.android.shared.date.util.now +@OptIn(ExperimentalMaterial3Api::class) @Composable @Destination -fun OutingApplicationScreen() { +fun OutingApplicationScreen( + navigator: OutingNavigator, + viewModel: OutingViewModel, +) { + val uiState by viewModel.stateFlow.collectAsStateWithLifecycle() + val (shouldShowStartTimePicker, onChangeShouldShowStartTimePicker) = remember { + mutableStateOf(false) + } + val startTimePickerState = rememberTimePickerState() + + if (shouldShowStartTimePicker) { + AlertDialog( + confirmButton = { + TextButton(onClick = { onChangeShouldShowStartTimePicker(false) }) { + Text(text = stringResource(id = R.string.close)) + } + }, + onDismissRequest = { onChangeShouldShowStartTimePicker(false) }, + text = { TimePicker(state = startTimePickerState) }, + ) + } + + val (shouldShowEndTimePicker, onChangeShouldShowEndTimePicker) = remember { + mutableStateOf(false) + } + val endTimePickerState = rememberTimePickerState() + + if (shouldShowEndTimePicker) { + AlertDialog( + confirmButton = { + TextButton(onClick = { onChangeShouldShowEndTimePicker(false) }) { + Text(text = stringResource(id = R.string.close)) + } + }, + onDismissRequest = { onChangeShouldShowEndTimePicker(false) }, + text = { TimePicker(state = endTimePickerState) }, + ) + } + + Scaffold( + topBar = { + DmsTopAppBar( + title = { Text(text = stringResource(id = R.string.outing_application)) }, + navigationIcon = { + IconButton(onClick = navigator::navigateUp) { + Icon( + painter = painterResource(id = R.drawable.ic_baseline_arrow_back_24), + contentDescription = stringResource(id = R.string.top_bar_back_button), + ) + } + }, + ) + }, + ) { padValues -> + Column( + modifier = Modifier + .fillMaxSize() + .padding(padValues), + verticalArrangement = Arrangement.spacedBy(DefaultVerticalSpace), + ) { + if (uiState.outingApplicationTime != null) { + val startTime = uiState.outingApplicationTime!!.startTime + val endTime = uiState.outingApplicationTime!!.endTime + FloatingNotice( + text = stringResource( + id = R.string.outing_format_application_time, + startTime.hour, + startTime.minute, + endTime.hour, + endTime.minute, + ), + ) + } + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(DefaultHorizontalSpace), + ) { + Spacer(modifier = Modifier.startPadding()) + OutingInputDefaults.Indicator() + Text( + text = stringResource(id = R.string.outing_is_required), + style = DmsTheme.typography.caption, + ) + Spacer(modifier = Modifier.endPadding()) + } + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(DefaultHorizontalSpace), + ) { + val capturedNow = remember { now } + Text( + modifier = Modifier.startPadding(), + fontWeight = FontWeight.Bold, + text = stringResource(id = R.string.outing_date), + ) + Text( + modifier = Modifier.endPadding(), + text = stringResource( + id = R.string.format_date_yyyy_mm_dd_day_of_week, + capturedNow.year, + capturedNow.month.value, + capturedNow.dayOfMonth, + capturedNow.dayOfWeek.text, + ), + ) + } + Spacer(modifier = Modifier.height(DefaultVerticalSpace)) + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(DefaultHorizontalSpace), + ) { + OutingInput( + modifier = Modifier + .weight(1f) + .startPadding(), + text = { Text(text = stringResource(id = R.string.outing_start_time)) }, + indicator = { OutingInputDefaults.Indicator() }, + ) { + TextField( + trailingIcon = { + IconButton( + onClick = { onChangeShouldShowStartTimePicker(true) }, + ) { + Icon( + painter = painterResource(id = R.drawable.ic_next), + contentDescription = stringResource( + id = R.string.outing_application_select_outing_time, + ), + tint = DmsTheme.colorScheme.icon, + ) + } + }, + value = stringResource( + id = R.string.outing_format_duration_h_m, + startTimePickerState.hour, + startTimePickerState.minute, + ), + onValueChange = {}, + readOnly = true, + ) + } + OutingInput( + modifier = Modifier + .weight(1f) + .endPadding(), + text = { Text(text = stringResource(id = R.string.outing_end_time)) }, + indicator = { OutingInputDefaults.Indicator() }, + ) { + TextField( + trailingIcon = { + IconButton( + onClick = { onChangeShouldShowEndTimePicker(true) }, + ) { + Icon( + painter = painterResource(id = R.drawable.ic_next), + contentDescription = stringResource( + id = R.string.outing_application_select_outing_time, + ), + tint = DmsTheme.colorScheme.icon, + ) + } + }, + value = stringResource( + id = R.string.outing_format_duration_h_m, + endTimePickerState.hour, + endTimePickerState.minute, + ), + onValueChange = {}, + readOnly = true, + ) + } + } + + val (outingTypeMenuExpanded, onChangeOutingTypeMenuExpanded) = remember { + mutableStateOf(false) + } + + Row( + modifier = Modifier.fillMaxWidth(), + horizontalArrangement = Arrangement.spacedBy(DefaultHorizontalSpace), + ) { + OutingInput( + modifier = Modifier + .weight(0.4f) + .startPadding(), + text = { Text(text = stringResource(id = R.string.outing_type)) }, + indicator = { OutingInputDefaults.Indicator() }, + ) { + ExposedDropdownMenuBox( + expanded = outingTypeMenuExpanded, + onExpandedChange = onChangeOutingTypeMenuExpanded, + ) { + TextField( + modifier = Modifier.menuAnchor(), + value = uiState.selectedOutingType + ?: stringResource(id = R.string.outing_select_outing_type), + onValueChange = {/* explicit blank */ }, + trailingIcon = { + ExposedDropdownMenuDefaults.TrailingIcon(expanded = outingTypeMenuExpanded) + }, + readOnly = true, + ) + ExposedDropdownMenu( + expanded = outingTypeMenuExpanded, + onDismissRequest = { onChangeOutingTypeMenuExpanded(false) }, + ) { + if (uiState.outingTypes != null) { + uiState.outingTypes!!.forEach { outingType -> + DropdownMenuItem( + text = { Text(text = outingType) }, + onClick = { + viewModel.postIntent( + OutingIntent.UpdateSelectedOutingType(outingType), + ) + }, + ) + } + } else { + DropdownMenuItem( + text = { + Text(text = stringResource(id = R.string.outing_error_there_is_no_outing_types)) + }, + onClick = { /* explicit blank */ }, + ) + } + } + } + } + OutingInput( + modifier = Modifier + .weight(0.6f) + .endPadding(), + text = { Text(text = stringResource(id = R.string.outing_companion_names)) }, + ) { + TextField( + value = stringResource(id = R.string.outing_add_companions), + onValueChange = { /* explicit blank */ }, + readOnly = true, + trailingIcon = { + IconButton(onClick = { /*TODO*/ }) { + Icon( + painter = painterResource(id = team.aliens.dms.android.core.designsystem.R.drawable.ic_plus), + contentDescription = stringResource(id = R.string.outing_add_companions), + ) + } + }, + ) + } + } + } + } } + +@Composable +private fun OutingInput( + modifier: Modifier = Modifier, + text: (@Composable () -> Unit)? = null, + indicator: (@Composable () -> Unit)? = null, + input: @Composable () -> Unit, +) { + Column( + modifier = modifier, + verticalArrangement = Arrangement.spacedBy(DefaultVerticalSpace), + ) { + Row { + if (text != null) { + text() + } + if (indicator != null) { + indicator() + } + } + input() + } +} + +object OutingInputDefaults { + + val IndicatorSize = DpSize( + width = 4.dp, + height = 4.dp, + ) + + val IndicatorColor: Color + @Composable get() = DmsTheme.colorScheme.primary + + @Composable + fun Indicator( + size: DpSize = IndicatorSize, + color: Color = IndicatorColor, + ) = Box( + modifier = Modifier.padding(4.dp), + contentAlignment = Alignment.Center, + ) { + Box( + modifier = Modifier + .size(size) + .background( + color = color, + shape = CircleShape, + ), + ) + } +} + +// TODO: move to :core:ui +@Stable +private val DayOfWeek.text: String + @Composable inline get() = stringResource( + id = when (this) { + DayOfWeek.MONDAY -> R.string.monday_abb + DayOfWeek.TUESDAY -> R.string.tuesday_abb + DayOfWeek.WEDNESDAY -> R.string.wednesday_abb + DayOfWeek.THURSDAY -> R.string.thursday_abb + DayOfWeek.FRIDAY -> R.string.friday_abb + DayOfWeek.SATURDAY -> R.string.saturday_abb + DayOfWeek.SUNDAY -> R.string.sunday_abb + }, + ) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt index a3332edfe..d1b09f759 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt @@ -9,7 +9,9 @@ import team.aliens.dms.android.core.ui.mvi.Intent import team.aliens.dms.android.core.ui.mvi.SideEffect import team.aliens.dms.android.core.ui.mvi.UiState import team.aliens.dms.android.data.outing.model.CurrentAppliedOutingApplication +import team.aliens.dms.android.data.outing.model.OutingApplicationTime import team.aliens.dms.android.data.outing.repository.OutingRepository +import team.aliens.dms.android.shared.date.util.now import javax.inject.Inject @HiltViewModel @@ -19,12 +21,28 @@ class OutingViewModel @Inject constructor( initialState = OutingUiState.initial(), ) { init { + fetchOutingApplicationTime() fetchCurrentAppliedOutingApplication() + fetchOutingTypes() } override fun processIntent(intent: OutingIntent) { when (intent) { is OutingIntent.CancelCurrentApplication -> cancelApplication() + is OutingIntent.UpdateSelectedOutingType -> updateSelectedOutingType(value = intent.value) + } + } + + private fun fetchOutingApplicationTime() = viewModelScope.launch(Dispatchers.IO) { + runCatching { + outingRepository.fetchOutingApplicationTimes(dayOfWeek = now.dayOfWeek) + }.onSuccess { + val outingApplicationTime = it.first() + reduce( + newState = stateFlow.value.copy( + outingApplicationTime = outingApplicationTime, + ), + ) } } @@ -45,21 +63,45 @@ class OutingViewModel @Inject constructor( private fun cancelApplication() = viewModelScope.launch(Dispatchers.IO) { } + + private fun fetchOutingTypes() = viewModelScope.launch(Dispatchers.IO) { + runCatching { + outingRepository.fetchOutingTypes("") + }.onSuccess { fetchedOutingTypes -> + reduce( + newState = stateFlow.value.copy( + outingTypes = fetchedOutingTypes, + ), + ) + } + } + + private fun updateSelectedOutingType(value: String) = reduce( + newState = stateFlow.value.copy( + selectedOutingType = value, + ), + ) } data class OutingUiState( - // val outingApplicationTime: List?, + val outingApplicationTime: OutingApplicationTime?, val currentAppliedOutingApplication: CurrentAppliedOutingApplication?, + val outingTypes: List?, + val selectedOutingType: String?, ) : UiState() { companion object { fun initial() = OutingUiState( + outingApplicationTime = null, currentAppliedOutingApplication = null, + outingTypes = null, + selectedOutingType = null, ) } } sealed class OutingIntent : Intent() { data object CancelCurrentApplication : OutingIntent() + class UpdateSelectedOutingType(val value: String) : OutingIntent() } sealed class OutingSideEffect : SideEffect() { From 9c90b8958c7db3bfc97594bfe897c927652a9b64 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 19 Mar 2024 22:20:51 +0900 Subject: [PATCH 064/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20text?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/outing/OutingApplicationScreen.kt | 31 +++++++++++++++++++ 1 file changed, 31 insertions(+) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt index c00330e34..b2e8bfe9f 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt @@ -26,6 +26,7 @@ import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -38,6 +39,7 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import org.threeten.bp.DayOfWeek import team.aliens.dms.android.core.designsystem.AlertDialog +import team.aliens.dms.android.core.designsystem.Button import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.Scaffold @@ -45,8 +47,10 @@ import team.aliens.dms.android.core.designsystem.TextButton import team.aliens.dms.android.core.designsystem.TextField import team.aliens.dms.android.core.ui.DefaultHorizontalSpace import team.aliens.dms.android.core.ui.DefaultVerticalSpace +import team.aliens.dms.android.core.ui.bottomPadding import team.aliens.dms.android.core.ui.composable.FloatingNotice import team.aliens.dms.android.core.ui.endPadding +import team.aliens.dms.android.core.ui.horizontalPadding import team.aliens.dms.android.core.ui.startPadding import team.aliens.dms.android.feature.R import team.aliens.dms.android.feature.outing.navigation.OutingNavigator @@ -305,6 +309,33 @@ fun OutingApplicationScreen( ) } } + + OutingInput( + modifier = Modifier + .weight(1f) + .horizontalPadding(), + ) { + var a by remember { + mutableStateOf("") + } + TextField( + modifier = Modifier.fillMaxSize(), + value = a, + onValueChange = { a = it }, + singleLine = false, + ) + } + + Button( + modifier = Modifier + .fillMaxWidth() + .startPadding() + .endPadding() + .bottomPadding(), + onClick = { /*TODO*/ }, + ) { + Text(text = stringResource(id = R.string.outing_do_application)) + } } } } From f0d95065371e048cdf319d3d53bb71bd3f8675e1 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Fri, 22 Mar 2024 09:25:27 +0900 Subject: [PATCH 065/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20retrofit?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gradle/libs.versions.toml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/gradle/libs.versions.toml b/gradle/libs.versions.toml index b9e10f787..3863c9049 100644 --- a/gradle/libs.versions.toml +++ b/gradle/libs.versions.toml @@ -75,7 +75,7 @@ okhttp-mockwebserver = { group = "com.squareup.okhttp3", name = "mockwebserver", okhttp-interceptor-logging = { group = "com.squareup.okhttp3", name = "logging-interceptor", version.ref = "okhttp" } retrofit = { group = "com.squareup.retrofit2", name = "retrofit", version.ref = "retrofit" } retrofit-converter-gson = { group = "com.squareup.retrofit2", name = "converter-gson", version.ref = "retrofit" } -retrofit-adapter-rxjava2 = { group = "com.squareup.retrofit2", name = "adapter-rxjava2", version.ref = "retrofit" } +retrofit-adapter-rxjava2 = { group = "com.squareup.retrofit2", name = "adapter-rxjava3", version.ref = "retrofit" } threetenbp = { module = "org.threeten:threetenbp", version.ref = "threetenbp" } hilt = { group = "com.google.dagger", name = "hilt-android", version.ref = "hilt" } hilt-testing = { module = "com.google.dagger:hilt-android-testing", version.ref = "hilt" } From 9e7734a38f0073865cc4974523ebf9f061946da9 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Fri, 22 Mar 2024 09:25:31 +0900 Subject: [PATCH 066/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20client?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/core/network/di/HttpClientModule.kt | 2 -- .../dms/android/core/network/util/HttpClientFactories.kt | 8 ++++---- 2 files changed, 4 insertions(+), 6 deletions(-) diff --git a/core/network/src/main/java/team/aliens/dms/android/core/network/di/HttpClientModule.kt b/core/network/src/main/java/team/aliens/dms/android/core/network/di/HttpClientModule.kt index d2ba0f2ba..0c40b9fbb 100644 --- a/core/network/src/main/java/team/aliens/dms/android/core/network/di/HttpClientModule.kt +++ b/core/network/src/main/java/team/aliens/dms/android/core/network/di/HttpClientModule.kt @@ -43,8 +43,6 @@ internal object HttpClientModule { ): Retrofit = Retrofit( client = globalOkHttpClient, baseUrl = baseUrl, - gsonConverter = true, - gsonLenient = true, ) @Provides diff --git a/core/network/src/main/java/team/aliens/dms/android/core/network/util/HttpClientFactories.kt b/core/network/src/main/java/team/aliens/dms/android/core/network/util/HttpClientFactories.kt index 879da4c0a..4b1d53743 100644 --- a/core/network/src/main/java/team/aliens/dms/android/core/network/util/HttpClientFactories.kt +++ b/core/network/src/main/java/team/aliens/dms/android/core/network/util/HttpClientFactories.kt @@ -6,7 +6,7 @@ import okhttp3.OkHttpClient import okhttp3.ResponseBody import retrofit2.Converter import retrofit2.Retrofit -import retrofit2.adapter.rxjava2.RxJava2CallAdapterFactory +import retrofit2.adapter.rxjava3.RxJava3CallAdapterFactory import retrofit2.converter.gson.GsonConverterFactory import java.lang.reflect.Type @@ -16,7 +16,7 @@ fun Retrofit( nullConverter: Boolean = true, gsonConverter: Boolean = true, gsonLenient: Boolean = true, - rxJava2CallAdapter: Boolean = true, + rxJava3CallAdapter: Boolean = true, ): Retrofit = Retrofit.Builder().baseUrl(baseUrl).apply { client(client) if (nullConverter) { @@ -30,8 +30,8 @@ fun Retrofit( } addConverterFactory(GsonConverterFactory.create(builder.create())) } - if (rxJava2CallAdapter) { - addCallAdapterFactory(RxJava2CallAdapterFactory.create()) + if (rxJava3CallAdapter) { + addCallAdapterFactory(RxJava3CallAdapterFactory.create()) } }.build() From 6ee4e1339a93e52d6caa6c0297c9d82c6f33efb6 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Fri, 22 Mar 2024 09:25:39 +0900 Subject: [PATCH 067/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20response?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/outing/repository/OutingRepository.kt | 10 +++++----- .../outing/repository/OutingRepositoryImpl.kt | 10 +++++----- .../outing/apiservice/OutingApiService.kt | 17 +++++++++++------ .../datasource/OutingNetworkDataSource.kt | 12 ++++++------ .../datasource/OutingNetworkDataSourceImpl.kt | 12 ++++++------ 5 files changed, 33 insertions(+), 28 deletions(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt index da8ae9f0f..6b4f155bc 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt @@ -9,9 +9,9 @@ import team.aliens.dms.android.data.outing.model.OutingApplicationTime import java.util.UUID abstract class OutingRepository { - abstract fun fetchOutingApplicationTimes(dayOfWeek: DayOfWeek): List + abstract suspend fun fetchOutingApplicationTimes(dayOfWeek: DayOfWeek): List - abstract fun applyOuting( + abstract suspend fun applyOuting( date: LocalDate, startTime: LocalDateTime, endTime: LocalDateTime, @@ -20,9 +20,9 @@ abstract class OutingRepository { companionIds: List, ): OutingApplicationId - abstract fun fetchCurrentAppliedOutingApplication(): CurrentAppliedOutingApplication + abstract suspend fun fetchCurrentAppliedOutingApplication(): CurrentAppliedOutingApplication - abstract fun cancelOuting(applicationId: UUID) + abstract suspend fun cancelOuting(applicationId: UUID) - abstract fun fetchOutingTypes(keyword: String): List + abstract suspend fun fetchOutingTypes(keyword: String): List } diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt index 28e9190da..56b5aa10e 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt @@ -15,10 +15,10 @@ import javax.inject.Inject class OutingRepositoryImpl @Inject constructor( private val outingNetworkDataSource: OutingNetworkDataSource, ) : OutingRepository() { - override fun fetchOutingApplicationTimes(dayOfWeek: DayOfWeek): List = + override suspend fun fetchOutingApplicationTimes(dayOfWeek: DayOfWeek): List = outingNetworkDataSource.fetchOutingAvailableTime(dayOfWeek = dayOfWeek.name).toModel() - override fun applyOuting( + override suspend fun applyOuting( date: LocalDate, startTime: LocalDateTime, endTime: LocalDateTime, @@ -36,13 +36,13 @@ class OutingRepositoryImpl @Inject constructor( ), ).applicationId - override fun fetchCurrentAppliedOutingApplication(): CurrentAppliedOutingApplication = + override suspend fun fetchCurrentAppliedOutingApplication(): CurrentAppliedOutingApplication = outingNetworkDataSource.fetchCurrentAppliedOutingApplication().toModel() - override fun cancelOuting(applicationId: UUID) { + override suspend fun cancelOuting(applicationId: UUID) { outingNetworkDataSource.cancelOuting(applicationId = applicationId) } - override fun fetchOutingTypes(keyword: String): List = + override suspend fun fetchOutingTypes(keyword: String): List = outingNetworkDataSource.fetchOutingTypes(keyword = keyword).titles } diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/apiservice/OutingApiService.kt b/network/src/main/java/team/aliens/dms/android/network/outing/apiservice/OutingApiService.kt index cabc2e415..123ede422 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/apiservice/OutingApiService.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/apiservice/OutingApiService.kt @@ -1,6 +1,7 @@ package team.aliens.dms.android.network.outing.apiservice import retrofit2.Response +import retrofit2.http.Body import retrofit2.http.DELETE import retrofit2.http.GET import retrofit2.http.POST @@ -17,26 +18,30 @@ import java.util.UUID interface OutingApiService { @GET("/outings/available-time") - fun fetchOutingAvailableTime(type: String): OutingAvailableTimeResponse + suspend fun fetchOutingAvailableTime( + @Query("dayOfWeek") dayOfWeek: String, + ): OutingAvailableTimeResponse @POST("/outings") - fun applyOuting(req: ApplyOutingRequest): ApplyOutingResponse + suspend fun applyOuting( + @Body req: ApplyOutingRequest, + ): ApplyOutingResponse @POST("/outings/{outing-application-id}") - fun fetchOutingApplicationDetails( + suspend fun fetchOutingApplicationDetails( @Path("outing-application-id") applicationId: UUID, ): FetchOutingApplicationDetailsResponse @GET("/outings/my") - fun fetchCurrentAppliedOutingApplication(): FetchCurrentAppliedOutingApplicationResponse + suspend fun fetchCurrentAppliedOutingApplication(): FetchCurrentAppliedOutingApplicationResponse @DELETE("/outing/{outing-application-id}") - fun cancelOuting( + suspend fun cancelOuting( @Path("outing-application-id") applicationId: UUID, ): Response @GET("/outing/types") - fun fetchOutingTypes( + suspend fun fetchOutingTypes( @Query("keyword") keyword: String?, ): FetchOutingTypesResponse } diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSource.kt b/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSource.kt index 5517bda77..c21825c75 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSource.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSource.kt @@ -10,10 +10,10 @@ import team.aliens.dms.android.network.outing.model.OutingAvailableTimeResponse import java.util.UUID abstract class OutingNetworkDataSource { - abstract fun fetchOutingAvailableTime(dayOfWeek: String): OutingAvailableTimeResponse - abstract fun applyOuting(req: ApplyOutingRequest): ApplyOutingResponse - abstract fun fetchOutingApplicationDetails(applicationId: UUID): FetchOutingApplicationDetailsResponse - abstract fun fetchCurrentAppliedOutingApplication(): FetchCurrentAppliedOutingApplicationResponse - abstract fun cancelOuting(applicationId: UUID): Response - abstract fun fetchOutingTypes(keyword: String?): FetchOutingTypesResponse + abstract suspend fun fetchOutingAvailableTime(dayOfWeek: String): OutingAvailableTimeResponse + abstract suspend fun applyOuting(req: ApplyOutingRequest): ApplyOutingResponse + abstract suspend fun fetchOutingApplicationDetails(applicationId: UUID): FetchOutingApplicationDetailsResponse + abstract suspend fun fetchCurrentAppliedOutingApplication(): FetchCurrentAppliedOutingApplicationResponse + abstract suspend fun cancelOuting(applicationId: UUID): Response + abstract suspend fun fetchOutingTypes(keyword: String?): FetchOutingTypesResponse } diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSourceImpl.kt b/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSourceImpl.kt index afcb569cf..17d3d80bb 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSourceImpl.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSourceImpl.kt @@ -14,21 +14,21 @@ import javax.inject.Inject class OutingNetworkDataSourceImpl @Inject constructor( private val outingApiService: OutingApiService, ) : OutingNetworkDataSource() { - override fun fetchOutingAvailableTime(dayOfWeek: String): OutingAvailableTimeResponse = + override suspend fun fetchOutingAvailableTime(dayOfWeek: String): OutingAvailableTimeResponse = outingApiService.fetchOutingAvailableTime(dayOfWeek) - override fun applyOuting(req: ApplyOutingRequest): ApplyOutingResponse = + override suspend fun applyOuting(req: ApplyOutingRequest): ApplyOutingResponse = outingApiService.applyOuting(req) - override fun fetchOutingApplicationDetails(applicationId: UUID): FetchOutingApplicationDetailsResponse = + override suspend fun fetchOutingApplicationDetails(applicationId: UUID): FetchOutingApplicationDetailsResponse = outingApiService.fetchOutingApplicationDetails(applicationId) - override fun fetchCurrentAppliedOutingApplication(): FetchCurrentAppliedOutingApplicationResponse = + override suspend fun fetchCurrentAppliedOutingApplication(): FetchCurrentAppliedOutingApplicationResponse = outingApiService.fetchCurrentAppliedOutingApplication() - override fun cancelOuting(applicationId: UUID): Response = + override suspend fun cancelOuting(applicationId: UUID): Response = outingApiService.cancelOuting(applicationId) - override fun fetchOutingTypes(keyword: String?): FetchOutingTypesResponse = + override suspend fun fetchOutingTypes(keyword: String?): FetchOutingTypesResponse = outingApiService.fetchOutingTypes(keyword) } From e9522c6ad51c29fde4c7451188c61c4e881b0fdf Mon Sep 17 00:00:00 2001 From: junsuPark Date: Fri, 22 Mar 2024 09:25:43 +0900 Subject: [PATCH 068/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20data=20class?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network/outing/model/OutingAvailableTimeResponse.kt | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt index 444f8e3bf..6b09e42ed 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt @@ -1,16 +1,18 @@ package team.aliens.dms.android.network.outing.model import com.google.gson.annotations.SerializedName +import org.threeten.bp.DayOfWeek import org.threeten.bp.LocalDateTime +import java.util.UUID data class OutingAvailableTimeResponse( @SerializedName("outing_available_time") val availableTimes: List, ) { data class AvailableTimeResponse( - @SerializedName("outing_available_time_id") val outingAvailableTimeId: String, + @SerializedName("outing_available_time_id") val id: UUID, @SerializedName("outing_time") val startTime: LocalDateTime, @SerializedName("arrival_time") val endTime: LocalDateTime, @SerializedName("enabled") val available: Boolean, - @SerializedName("day_of_week") val dayOfWeek: String, + @SerializedName("day_of_week") val dayOfWeek: DayOfWeek, ) } From b21fd189dec39e8179772c6159e7da0dd2d43fe4 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Fri, 22 Mar 2024 09:25:46 +0900 Subject: [PATCH 069/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20data=20class?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/data/outing/model/OutingApplicationTime.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt b/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt index 6622309c2..28d445dd8 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt @@ -21,9 +21,9 @@ fun List.toModel(): List Date: Fri, 22 Mar 2024 09:45:41 +0900 Subject: [PATCH 070/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20serv?= =?UTF-8?q?ice?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/data/outing/repository/OutingRepository.kt | 2 +- .../data/outing/repository/OutingRepositoryImpl.kt | 2 +- .../android/network/outing/apiservice/OutingApiService.kt | 8 +++----- .../outing/datasource/OutingNetworkDataSourceImpl.kt | 2 +- .../network/outing/model/OutingAvailableTimeResponse.kt | 4 ++-- 5 files changed, 8 insertions(+), 10 deletions(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt index 6b4f155bc..4fb15db9a 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt @@ -24,5 +24,5 @@ abstract class OutingRepository { abstract suspend fun cancelOuting(applicationId: UUID) - abstract suspend fun fetchOutingTypes(keyword: String): List + abstract suspend fun fetchOutingTypes(keyword: String?): List } diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt index 56b5aa10e..2f7f2b7bd 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt @@ -43,6 +43,6 @@ class OutingRepositoryImpl @Inject constructor( outingNetworkDataSource.cancelOuting(applicationId = applicationId) } - override suspend fun fetchOutingTypes(keyword: String): List = + override suspend fun fetchOutingTypes(keyword: String?): List = outingNetworkDataSource.fetchOutingTypes(keyword = keyword).titles } diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/apiservice/OutingApiService.kt b/network/src/main/java/team/aliens/dms/android/network/outing/apiservice/OutingApiService.kt index 123ede422..7d2d3506e 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/apiservice/OutingApiService.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/apiservice/OutingApiService.kt @@ -35,13 +35,11 @@ interface OutingApiService { @GET("/outings/my") suspend fun fetchCurrentAppliedOutingApplication(): FetchCurrentAppliedOutingApplicationResponse - @DELETE("/outing/{outing-application-id}") + @DELETE("/outings/{outing-application-id}") suspend fun cancelOuting( @Path("outing-application-id") applicationId: UUID, ): Response - @GET("/outing/types") - suspend fun fetchOutingTypes( - @Query("keyword") keyword: String?, - ): FetchOutingTypesResponse + @GET("/outings/types") + suspend fun fetchOutingTypes(): FetchOutingTypesResponse } diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSourceImpl.kt b/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSourceImpl.kt index 17d3d80bb..781f636df 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSourceImpl.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/datasource/OutingNetworkDataSourceImpl.kt @@ -30,5 +30,5 @@ class OutingNetworkDataSourceImpl @Inject constructor( outingApiService.cancelOuting(applicationId) override suspend fun fetchOutingTypes(keyword: String?): FetchOutingTypesResponse = - outingApiService.fetchOutingTypes(keyword) + outingApiService.fetchOutingTypes() } diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt index 6b09e42ed..7ddfdeae9 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt @@ -9,10 +9,10 @@ data class OutingAvailableTimeResponse( @SerializedName("outing_available_time") val availableTimes: List, ) { data class AvailableTimeResponse( - @SerializedName("outing_available_time_id") val id: UUID, + @SerializedName("outing_available_time_id") val id: String, @SerializedName("outing_time") val startTime: LocalDateTime, @SerializedName("arrival_time") val endTime: LocalDateTime, @SerializedName("enabled") val available: Boolean, - @SerializedName("day_of_week") val dayOfWeek: DayOfWeek, + @SerializedName("day_of_week") val dayOfWeek: String, ) } From a2e0c4a1320bf47609cd4264381934ecc294f98f Mon Sep 17 00:00:00 2001 From: junsuPark Date: Fri, 22 Mar 2024 09:45:45 +0900 Subject: [PATCH 071/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20time?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/data/outing/model/OutingApplicationTime.kt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt b/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt index 28d445dd8..40a9fce69 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt @@ -21,9 +21,9 @@ fun List.toModel(): List Date: Fri, 22 Mar 2024 09:46:00 +0900 Subject: [PATCH 072/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20appl?= =?UTF-8?q?ication?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/outing/OutingApplicationScreen.kt | 8 ++----- .../android/feature/outing/OutingViewModel.kt | 22 ++++++++++++++----- 2 files changed, 19 insertions(+), 11 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt index b2e8bfe9f..e65904e2b 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt @@ -26,7 +26,6 @@ import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember -import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.graphics.Color @@ -315,13 +314,10 @@ fun OutingApplicationScreen( .weight(1f) .horizontalPadding(), ) { - var a by remember { - mutableStateOf("") - } TextField( modifier = Modifier.fillMaxSize(), - value = a, - onValueChange = { a = it }, + value = uiState.reason, + onValueChange = { viewModel.postIntent(OutingIntent.UpdateReason(value = it)) }, singleLine = false, ) } diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt index d1b09f759..79ee7a97d 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt @@ -12,6 +12,7 @@ import team.aliens.dms.android.data.outing.model.CurrentAppliedOutingApplication import team.aliens.dms.android.data.outing.model.OutingApplicationTime import team.aliens.dms.android.data.outing.repository.OutingRepository import team.aliens.dms.android.shared.date.util.now +import team.aliens.dms.android.shared.date.util.today import javax.inject.Inject @HiltViewModel @@ -30,19 +31,21 @@ class OutingViewModel @Inject constructor( when (intent) { is OutingIntent.CancelCurrentApplication -> cancelApplication() is OutingIntent.UpdateSelectedOutingType -> updateSelectedOutingType(value = intent.value) + is OutingIntent.UpdateReason -> updateReason(value = intent.value) } } private fun fetchOutingApplicationTime() = viewModelScope.launch(Dispatchers.IO) { runCatching { - outingRepository.fetchOutingApplicationTimes(dayOfWeek = now.dayOfWeek) - }.onSuccess { - val outingApplicationTime = it.first() + outingRepository.fetchOutingApplicationTimes(dayOfWeek = today.dayOfWeek) + }.onSuccess { fetchedApplicationTime -> reduce( newState = stateFlow.value.copy( - outingApplicationTime = outingApplicationTime, + outingApplicationTime = fetchedApplicationTime.first(), ), ) + }.onFailure { + it.printStackTrace() } } @@ -66,7 +69,7 @@ class OutingViewModel @Inject constructor( private fun fetchOutingTypes() = viewModelScope.launch(Dispatchers.IO) { runCatching { - outingRepository.fetchOutingTypes("") + outingRepository.fetchOutingTypes(null) }.onSuccess { fetchedOutingTypes -> reduce( newState = stateFlow.value.copy( @@ -81,6 +84,12 @@ class OutingViewModel @Inject constructor( selectedOutingType = value, ), ) + + private fun updateReason(value: String) = reduce( + newState = stateFlow.value.copy( + reason = value, + ), + ) } data class OutingUiState( @@ -88,6 +97,7 @@ data class OutingUiState( val currentAppliedOutingApplication: CurrentAppliedOutingApplication?, val outingTypes: List?, val selectedOutingType: String?, + val reason: String, ) : UiState() { companion object { fun initial() = OutingUiState( @@ -95,6 +105,7 @@ data class OutingUiState( currentAppliedOutingApplication = null, outingTypes = null, selectedOutingType = null, + reason = "", ) } } @@ -102,6 +113,7 @@ data class OutingUiState( sealed class OutingIntent : Intent() { data object CancelCurrentApplication : OutingIntent() class UpdateSelectedOutingType(val value: String) : OutingIntent() + class UpdateReason(val value: String) : OutingIntent() } sealed class OutingSideEffect : SideEffect() { From e0b1a51c8eaa98e9c2b942a2758f1129875df1ea Mon Sep 17 00:00:00 2001 From: junsuPark Date: Fri, 22 Mar 2024 10:12:46 +0900 Subject: [PATCH 073/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20time?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/outing/OutingApplicationScreen.kt | 50 ++++++++++++------- .../android/feature/outing/OutingViewModel.kt | 42 +++++++++++++--- 2 files changed, 67 insertions(+), 25 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt index e65904e2b..1523c2a7c 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt @@ -53,7 +53,6 @@ import team.aliens.dms.android.core.ui.horizontalPadding import team.aliens.dms.android.core.ui.startPadding import team.aliens.dms.android.feature.R import team.aliens.dms.android.feature.outing.navigation.OutingNavigator -import team.aliens.dms.android.shared.date.util.now @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -63,16 +62,25 @@ fun OutingApplicationScreen( viewModel: OutingViewModel, ) { val uiState by viewModel.stateFlow.collectAsStateWithLifecycle() + val (outingTypeMenuExpanded, onChangeOutingTypeMenuExpanded) = remember { + mutableStateOf(false) + } + + val startTimePickerState = rememberTimePickerState() val (shouldShowStartTimePicker, onChangeShouldShowStartTimePicker) = remember { mutableStateOf(false) } - val startTimePickerState = rememberTimePickerState() if (shouldShowStartTimePicker) { AlertDialog( confirmButton = { - TextButton(onClick = { onChangeShouldShowStartTimePicker(false) }) { + TextButton( + onClick = { + viewModel.postIntent(OutingIntent.UpdateOutingStartTime(value = "${startTimePickerState.hour}:${startTimePickerState.minute}")) + onChangeShouldShowStartTimePicker(false) + }, + ) { Text(text = stringResource(id = R.string.close)) } }, @@ -81,15 +89,20 @@ fun OutingApplicationScreen( ) } + val endTimePickerState = rememberTimePickerState() val (shouldShowEndTimePicker, onChangeShouldShowEndTimePicker) = remember { mutableStateOf(false) } - val endTimePickerState = rememberTimePickerState() if (shouldShowEndTimePicker) { AlertDialog( confirmButton = { - TextButton(onClick = { onChangeShouldShowEndTimePicker(false) }) { + TextButton( + onClick = { + viewModel.postIntent(OutingIntent.UpdateOutingEndTime(value = "${endTimePickerState.hour}:${endTimePickerState.minute}")) + onChangeShouldShowEndTimePicker(false) + }, + ) { Text(text = stringResource(id = R.string.close)) } }, @@ -148,7 +161,6 @@ fun OutingApplicationScreen( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(DefaultHorizontalSpace), ) { - val capturedNow = remember { now } Text( modifier = Modifier.startPadding(), fontWeight = FontWeight.Bold, @@ -158,10 +170,10 @@ fun OutingApplicationScreen( modifier = Modifier.endPadding(), text = stringResource( id = R.string.format_date_yyyy_mm_dd_day_of_week, - capturedNow.year, - capturedNow.month.value, - capturedNow.dayOfMonth, - capturedNow.dayOfWeek.text, + uiState.capturedNow.year, + uiState.capturedNow.month.value, + uiState.capturedNow.dayOfMonth, + uiState.capturedNow.dayOfWeek.text, ), ) } @@ -177,6 +189,9 @@ fun OutingApplicationScreen( text = { Text(text = stringResource(id = R.string.outing_start_time)) }, indicator = { OutingInputDefaults.Indicator() }, ) { + val time = remember(uiState.selectedOutingStartTime) { + uiState.selectedOutingStartTime.split(':').map(String::toInt) + } TextField( trailingIcon = { IconButton( @@ -193,8 +208,8 @@ fun OutingApplicationScreen( }, value = stringResource( id = R.string.outing_format_duration_h_m, - startTimePickerState.hour, - startTimePickerState.minute, + time[0].toInt(), + time[1].toInt(), ), onValueChange = {}, readOnly = true, @@ -207,6 +222,9 @@ fun OutingApplicationScreen( text = { Text(text = stringResource(id = R.string.outing_end_time)) }, indicator = { OutingInputDefaults.Indicator() }, ) { + val time = remember(uiState.selectedOutingEndTime) { + uiState.selectedOutingEndTime.split(':').map(String::toInt) + } TextField( trailingIcon = { IconButton( @@ -223,8 +241,8 @@ fun OutingApplicationScreen( }, value = stringResource( id = R.string.outing_format_duration_h_m, - endTimePickerState.hour, - endTimePickerState.minute, + time[0], + time[1], ), onValueChange = {}, readOnly = true, @@ -232,10 +250,6 @@ fun OutingApplicationScreen( } } - val (outingTypeMenuExpanded, onChangeOutingTypeMenuExpanded) = remember { - mutableStateOf(false) - } - Row( modifier = Modifier.fillMaxWidth(), horizontalArrangement = Arrangement.spacedBy(DefaultHorizontalSpace), diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt index 79ee7a97d..159137283 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt @@ -4,6 +4,7 @@ import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch +import org.threeten.bp.LocalDateTime import team.aliens.dms.android.core.ui.mvi.BaseMviViewModel import team.aliens.dms.android.core.ui.mvi.Intent import team.aliens.dms.android.core.ui.mvi.SideEffect @@ -32,6 +33,8 @@ class OutingViewModel @Inject constructor( is OutingIntent.CancelCurrentApplication -> cancelApplication() is OutingIntent.UpdateSelectedOutingType -> updateSelectedOutingType(value = intent.value) is OutingIntent.UpdateReason -> updateReason(value = intent.value) + is OutingIntent.UpdateOutingStartTime -> updateOutingStartTime(value = intent.value) + is OutingIntent.UpdateOutingEndTime -> updateOutingEndTime(value = intent.value) } } @@ -90,6 +93,19 @@ class OutingViewModel @Inject constructor( reason = value, ), ) + + private fun updateOutingStartTime(value: String) = reduce( + newState = stateFlow.value.copy( + selectedOutingStartTime = value, + ), + ) + + + private fun updateOutingEndTime(value: String) = reduce( + newState = stateFlow.value.copy( + selectedOutingEndTime = value, + ), + ) } data class OutingUiState( @@ -98,15 +114,25 @@ data class OutingUiState( val outingTypes: List?, val selectedOutingType: String?, val reason: String, + val capturedNow: LocalDateTime, + val selectedOutingStartTime: String, + val selectedOutingEndTime: String, ) : UiState() { companion object { - fun initial() = OutingUiState( - outingApplicationTime = null, - currentAppliedOutingApplication = null, - outingTypes = null, - selectedOutingType = null, - reason = "", - ) + fun initial(): OutingUiState { + val capturedNow = now + return OutingUiState( + outingApplicationTime = null, + currentAppliedOutingApplication = null, + outingTypes = null, + selectedOutingType = null, + reason = "", + capturedNow = capturedNow, + // TODO: remove hard-coded string resources from viewmodel + selectedOutingEndTime = "${capturedNow.hour}:${capturedNow.minute}", + selectedOutingStartTime = "${capturedNow.hour}:${capturedNow.minute}", + ) + } } } @@ -114,6 +140,8 @@ sealed class OutingIntent : Intent() { data object CancelCurrentApplication : OutingIntent() class UpdateSelectedOutingType(val value: String) : OutingIntent() class UpdateReason(val value: String) : OutingIntent() + class UpdateOutingStartTime(val value: String) : OutingIntent() + class UpdateOutingEndTime(val value: String) : OutingIntent() } sealed class OutingSideEffect : SideEffect() { From 2fd8cd5e391d555fc1734d0359efdc24f61ddb2d Mon Sep 17 00:00:00 2001 From: junsuPark Date: Fri, 22 Mar 2024 10:22:41 +0900 Subject: [PATCH 074/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20application?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/feature/outing/OutingApplicationScreen.kt | 4 ++++ feature/src/main/res/values/strings.xml | 1 + 2 files changed, 5 insertions(+) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt index 1523c2a7c..17fdb9032 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt @@ -287,6 +287,7 @@ fun OutingApplicationScreen( viewModel.postIntent( OutingIntent.UpdateSelectedOutingType(outingType), ) + onChangeOutingTypeMenuExpanded(false) }, ) } @@ -333,6 +334,9 @@ fun OutingApplicationScreen( value = uiState.reason, onValueChange = { viewModel.postIntent(OutingIntent.UpdateReason(value = it)) }, singleLine = false, + hint = { + Text(text = stringResource(id = R.string.outing_hint_please_enter_description)) + }, ) } diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index 99507ce89..31bd39e0c 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -311,4 +311,5 @@ %04d.%02d.%02d (%s) 외출 시간 복귀 시간 + 내용을 입력해 주세요 \ No newline at end of file From c3497bee8b028907d2448dea8191436144a73ae1 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Fri, 22 Mar 2024 10:50:32 +0900 Subject: [PATCH 075/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/data/outing/repository/OutingRepository.kt | 4 ++-- .../android/data/outing/repository/OutingRepositoryImpl.kt | 4 ++-- .../dms/android/network/outing/model/ApplyOutingRequest.kt | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt index 4fb15db9a..eb768f2df 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt @@ -13,8 +13,8 @@ abstract class OutingRepository { abstract suspend fun applyOuting( date: LocalDate, - startTime: LocalDateTime, - endTime: LocalDateTime, + startTime: String, + endTime: String, type: String, reason: String?, companionIds: List, diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt index 2f7f2b7bd..b47cfc9da 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt @@ -20,8 +20,8 @@ class OutingRepositoryImpl @Inject constructor( override suspend fun applyOuting( date: LocalDate, - startTime: LocalDateTime, - endTime: LocalDateTime, + startTime: String, + endTime: String, type: String, reason: String?, companionIds: List diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt index c87d78aed..6f24e2539 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt @@ -7,8 +7,8 @@ import java.util.UUID data class ApplyOutingRequest( @SerializedName("outing_date") val date: LocalDate, - @SerializedName("outing_time") val startTime: LocalDateTime, - @SerializedName("arrival_time") val endTime: LocalDateTime, + @SerializedName("outing_time") val startTime: String, + @SerializedName("arrival_time") val endTime: String, @SerializedName("outing_type_title") val type: String, @SerializedName("reason") val reason: String?, @SerializedName("companion_ids") val companionIds: List, From 1e904ae1a29b7b6f3945b3a687f0e888b2c396d9 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 28 Mar 2024 08:27:48 +0900 Subject: [PATCH 076/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20student?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aliens/dms/android/data/student/model/Student.kt | 10 ++++++++++ 1 file changed, 10 insertions(+) create mode 100644 data/src/main/java/team/aliens/dms/android/data/student/model/Student.kt diff --git a/data/src/main/java/team/aliens/dms/android/data/student/model/Student.kt b/data/src/main/java/team/aliens/dms/android/data/student/model/Student.kt new file mode 100644 index 000000000..3814543e9 --- /dev/null +++ b/data/src/main/java/team/aliens/dms/android/data/student/model/Student.kt @@ -0,0 +1,10 @@ +package team.aliens.dms.android.data.student.model + +import com.google.gson.annotations.SerializedName + +data class Student( + @SerializedName("id") val id: String, + @SerializedName("name") val name: String, + @SerializedName("gcn") val gradeClassNumber: String, + @SerializedName("profile_image_url") val profileImageUrl: String, +) From edfdfb710a71052050054ac54aa207497f69500a Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 28 Mar 2024 08:32:40 +0900 Subject: [PATCH 077/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20student=20mod?= =?UTF-8?q?el?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aliens/dms/android/data/student/model/Student.kt | 10 ++++------ .../network/student/model/FetchStudentsResponse.kt | 10 ++++++++++ 2 files changed, 14 insertions(+), 6 deletions(-) create mode 100644 network/src/main/java/team/aliens/dms/android/network/student/model/FetchStudentsResponse.kt diff --git a/data/src/main/java/team/aliens/dms/android/data/student/model/Student.kt b/data/src/main/java/team/aliens/dms/android/data/student/model/Student.kt index 3814543e9..bf7294297 100644 --- a/data/src/main/java/team/aliens/dms/android/data/student/model/Student.kt +++ b/data/src/main/java/team/aliens/dms/android/data/student/model/Student.kt @@ -1,10 +1,8 @@ package team.aliens.dms.android.data.student.model -import com.google.gson.annotations.SerializedName - data class Student( - @SerializedName("id") val id: String, - @SerializedName("name") val name: String, - @SerializedName("gcn") val gradeClassNumber: String, - @SerializedName("profile_image_url") val profileImageUrl: String, + val id: String, + val name: String, + val gradeClassNumber: String, + val profileImageUrl: String, ) diff --git a/network/src/main/java/team/aliens/dms/android/network/student/model/FetchStudentsResponse.kt b/network/src/main/java/team/aliens/dms/android/network/student/model/FetchStudentsResponse.kt new file mode 100644 index 000000000..3d3e9dec0 --- /dev/null +++ b/network/src/main/java/team/aliens/dms/android/network/student/model/FetchStudentsResponse.kt @@ -0,0 +1,10 @@ +package team.aliens.dms.android.network.student.model + +import com.google.gson.annotations.SerializedName + +data class FetchStudentsResponse( + @SerializedName("id") val id: String, + @SerializedName("name") val name: String, + @SerializedName("gcn") val gradeClassNumber: String, + @SerializedName("profile_image_url") val profileImageUrl: String, +) From b824c24b8112c9142627b0faaeea433907374f11 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 28 Mar 2024 08:35:07 +0900 Subject: [PATCH 078/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20fetch=20stude?= =?UTF-8?q?nts=20response?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network/student/model/FetchStudentsResponse.kt | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/network/src/main/java/team/aliens/dms/android/network/student/model/FetchStudentsResponse.kt b/network/src/main/java/team/aliens/dms/android/network/student/model/FetchStudentsResponse.kt index 3d3e9dec0..af7e1779e 100644 --- a/network/src/main/java/team/aliens/dms/android/network/student/model/FetchStudentsResponse.kt +++ b/network/src/main/java/team/aliens/dms/android/network/student/model/FetchStudentsResponse.kt @@ -3,8 +3,12 @@ package team.aliens.dms.android.network.student.model import com.google.gson.annotations.SerializedName data class FetchStudentsResponse( - @SerializedName("id") val id: String, - @SerializedName("name") val name: String, - @SerializedName("gcn") val gradeClassNumber: String, - @SerializedName("profile_image_url") val profileImageUrl: String, -) + @SerializedName("students") val students: List, +) { + data class StudentResponse( + @SerializedName("id") val id: String, + @SerializedName("name") val name: String, + @SerializedName("gcn") val gradeClassNumber: String, + @SerializedName("profile_image_url") val profileImageUrl: String, + ) +} From b906c023947d1a6c8f97402f9faa61c864032353 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 28 Mar 2024 08:35:14 +0900 Subject: [PATCH 079/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20api?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/network/student/apiservice/StudentApiService.kt | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/network/src/main/java/team/aliens/dms/android/network/student/apiservice/StudentApiService.kt b/network/src/main/java/team/aliens/dms/android/network/student/apiservice/StudentApiService.kt index feadee987..2490e979d 100644 --- a/network/src/main/java/team/aliens/dms/android/network/student/apiservice/StudentApiService.kt +++ b/network/src/main/java/team/aliens/dms/android/network/student/apiservice/StudentApiService.kt @@ -11,6 +11,7 @@ import team.aliens.dms.android.core.jwt.RequiresAccessToken import team.aliens.dms.android.network.student.model.EditProfileRequest import team.aliens.dms.android.network.student.model.ExamineStudentNumberResponse import team.aliens.dms.android.network.student.model.FetchMyPageResponse +import team.aliens.dms.android.network.student.model.FetchStudentsResponse import team.aliens.dms.android.network.student.model.FindIdResponse import team.aliens.dms.android.network.student.model.ResetPasswordRequest import team.aliens.dms.android.network.student.model.SignUpRequest @@ -59,4 +60,7 @@ internal interface StudentApiService { @DELETE("/students") @RequiresAccessToken suspend fun withdraw() + + @GET("/students") + suspend fun fetchStudents(): FetchStudentsResponse } From 8f7e5ece465c229f59bf432dde126ef885ae91cc Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 28 Mar 2024 08:35:19 +0900 Subject: [PATCH 080/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20student=20rep?= =?UTF-8?q?ository?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/data/student/repository/StudentRepository.kt | 3 +++ .../data/student/repository/StudentRepositoryImpl.kt | 8 +++++--- 2 files changed, 8 insertions(+), 3 deletions(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepository.kt b/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepository.kt index 56298144d..799afe072 100644 --- a/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepository.kt +++ b/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepository.kt @@ -2,6 +2,7 @@ package team.aliens.dms.android.data.student.repository import team.aliens.dms.android.data.student.model.HashedEmail import team.aliens.dms.android.data.student.model.MyPage +import team.aliens.dms.android.data.student.model.Student import team.aliens.dms.android.data.student.model.StudentName import java.util.UUID @@ -52,4 +53,6 @@ abstract class StudentRepository { abstract suspend fun editProfile(profileImageUrl: String) abstract suspend fun withdraw() + + abstract suspend fun fetchStudents(): List } diff --git a/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt b/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt index 13321c844..6e73fdb08 100644 --- a/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt +++ b/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt @@ -5,6 +5,7 @@ import team.aliens.dms.android.core.school.SchoolProvider import team.aliens.dms.android.data.student.mapper.toModel import team.aliens.dms.android.data.student.model.HashedEmail import team.aliens.dms.android.data.student.model.MyPage +import team.aliens.dms.android.data.student.model.Student import team.aliens.dms.android.data.student.model.StudentName import team.aliens.dms.android.network.student.datasource.NetworkStudentDataSource import team.aliens.dms.android.network.student.model.SignUpRequest @@ -100,9 +101,10 @@ internal class StudentRepositoryImpl @Inject constructor( } override suspend fun withdraw() { - // TODO: remove docs - /*networkStudentDataSource.withdraw() + networkStudentDataSource.withdraw() jwtProvider.clearCaches() - schoolProvider.clearCaches()*/ + schoolProvider.clearCaches() } + + override suspend fun fetchStudents(): List =networkStudentDataSource.fetchStudents() } From 39363528000164458b9d70e6690957a8f081d53a Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 28 Mar 2024 08:35:28 +0900 Subject: [PATCH 081/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20student=20dts?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../network/student/datasource/NetworkStudentDataSource.kt | 3 +++ .../network/student/datasource/NetworkStudentDataSourceImpl.kt | 3 +++ 2 files changed, 6 insertions(+) diff --git a/network/src/main/java/team/aliens/dms/android/network/student/datasource/NetworkStudentDataSource.kt b/network/src/main/java/team/aliens/dms/android/network/student/datasource/NetworkStudentDataSource.kt index 85d7c1eb8..a0ca73258 100644 --- a/network/src/main/java/team/aliens/dms/android/network/student/datasource/NetworkStudentDataSource.kt +++ b/network/src/main/java/team/aliens/dms/android/network/student/datasource/NetworkStudentDataSource.kt @@ -3,6 +3,7 @@ package team.aliens.dms.android.network.student.datasource import team.aliens.dms.android.network.student.model.EditProfileRequest import team.aliens.dms.android.network.student.model.ExamineStudentNumberResponse import team.aliens.dms.android.network.student.model.FetchMyPageResponse +import team.aliens.dms.android.network.student.model.FetchStudentsResponse import team.aliens.dms.android.network.student.model.FindIdResponse import team.aliens.dms.android.network.student.model.ResetPasswordRequest import team.aliens.dms.android.network.student.model.SignUpRequest @@ -39,4 +40,6 @@ abstract class NetworkStudentDataSource { abstract suspend fun editProfile(request: EditProfileRequest) abstract suspend fun withdraw() + + abstract suspend fun fetchStudents(): FetchStudentsResponse } diff --git a/network/src/main/java/team/aliens/dms/android/network/student/datasource/NetworkStudentDataSourceImpl.kt b/network/src/main/java/team/aliens/dms/android/network/student/datasource/NetworkStudentDataSourceImpl.kt index 9941002d9..19cd4f0c0 100644 --- a/network/src/main/java/team/aliens/dms/android/network/student/datasource/NetworkStudentDataSourceImpl.kt +++ b/network/src/main/java/team/aliens/dms/android/network/student/datasource/NetworkStudentDataSourceImpl.kt @@ -5,6 +5,7 @@ import team.aliens.dms.android.network.student.apiservice.StudentApiService import team.aliens.dms.android.network.student.model.EditProfileRequest import team.aliens.dms.android.network.student.model.ExamineStudentNumberResponse import team.aliens.dms.android.network.student.model.FetchMyPageResponse +import team.aliens.dms.android.network.student.model.FetchStudentsResponse import team.aliens.dms.android.network.student.model.FindIdResponse import team.aliens.dms.android.network.student.model.ResetPasswordRequest import team.aliens.dms.android.network.student.model.SignUpRequest @@ -60,4 +61,6 @@ internal class NetworkStudentDataSourceImpl @Inject constructor( handleNetworkRequest { studentApiService.editProfile(request) } override suspend fun withdraw() = handleNetworkRequest { studentApiService.withdraw() } + override suspend fun fetchStudents(): FetchStudentsResponse = + handleNetworkRequest { studentApiService.fetchStudents() } } From f318e4dc29e3b00626a3bcecc14ca10ed127403d Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 28 Mar 2024 08:37:17 +0900 Subject: [PATCH 082/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20student=20rep?= =?UTF-8?q?ository=20mapper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aliens/dms/android/data/student/model/Student.kt | 12 ++++++++++++ .../data/student/repository/StudentRepositoryImpl.kt | 4 +++- 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/student/model/Student.kt b/data/src/main/java/team/aliens/dms/android/data/student/model/Student.kt index bf7294297..4f4781939 100644 --- a/data/src/main/java/team/aliens/dms/android/data/student/model/Student.kt +++ b/data/src/main/java/team/aliens/dms/android/data/student/model/Student.kt @@ -1,8 +1,20 @@ package team.aliens.dms.android.data.student.model +import team.aliens.dms.android.network.student.model.FetchStudentsResponse + data class Student( val id: String, val name: String, val gradeClassNumber: String, val profileImageUrl: String, ) + +fun FetchStudentsResponse.toModel(): List = + this.students.map(FetchStudentsResponse.StudentResponse::toModel) + +fun FetchStudentsResponse.StudentResponse.toModel(): Student = Student( + id = this.id, + name = this.name, + gradeClassNumber = this.gradeClassNumber, + profileImageUrl = this.profileImageUrl, +) diff --git a/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt b/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt index 6e73fdb08..2d4b9c0a6 100644 --- a/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt +++ b/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt @@ -7,6 +7,7 @@ import team.aliens.dms.android.data.student.model.HashedEmail import team.aliens.dms.android.data.student.model.MyPage import team.aliens.dms.android.data.student.model.Student import team.aliens.dms.android.data.student.model.StudentName +import team.aliens.dms.android.data.student.model.toModel import team.aliens.dms.android.network.student.datasource.NetworkStudentDataSource import team.aliens.dms.android.network.student.model.SignUpRequest import team.aliens.dms.android.network.student.model.SignUpResponse @@ -106,5 +107,6 @@ internal class StudentRepositoryImpl @Inject constructor( schoolProvider.clearCaches() } - override suspend fun fetchStudents(): List =networkStudentDataSource.fetchStudents() + override suspend fun fetchStudents(): List = + networkStudentDataSource.fetchStudents().toModel() } From f409f6ceb39eda00ed33647ff4daa88e7aa1d2a5 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 28 Mar 2024 09:23:05 +0900 Subject: [PATCH 083/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20uuid?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/feature/outing/OutingStatusScreen.kt | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt index 92fa826c0..2874841c4 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt @@ -48,7 +48,6 @@ import team.aliens.dms.android.core.ui.topPadding import team.aliens.dms.android.core.ui.verticalPadding import team.aliens.dms.android.feature.R import team.aliens.dms.android.feature.outing.navigation.OutingNavigator -import java.util.UUID @OptIn(ExperimentalMaterial3Api::class) @Destination @@ -90,6 +89,9 @@ fun OutingStatusScreen( OutingSideEffect.CurrentAppliedOutingApplicationNotFound -> toast.showErrorToast( message = context.getString(R.string.outing_failed_to_fetch_current_applied_outing_application), ) + + else -> {/* explicit blank */ + } } } @@ -128,7 +130,6 @@ fun OutingStatusScreen( ) uiState.currentAppliedOutingApplication?.let { outingApplication -> OutingInformationCard( - outingId = UUID.randomUUID(), title = outingApplication.type, date = outingApplication.date, time = stringResource( @@ -138,7 +139,8 @@ fun OutingStatusScreen( ), companionNames = outingApplication.companionNames, reason = outingApplication.reason, - onCancelApplication = { onChangeShouldShowCancelOutingDialog(true) }) + onCancelApplication = { onChangeShouldShowCancelOutingDialog(true) }, + ) } } if (uiState.currentAppliedOutingApplication == null) { @@ -159,7 +161,6 @@ fun OutingStatusScreen( @Composable private fun OutingInformationCard( modifier: Modifier = Modifier, - outingId: UUID, title: String, date: LocalDate, time: String, From 16ca22647a71deb390d3f348cc09a0beaf38f5b3 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Thu, 28 Mar 2024 09:23:08 +0900 Subject: [PATCH 084/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20init?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/outing/OutingViewModel.kt | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt index 159137283..e6afa429e 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt @@ -12,13 +12,17 @@ import team.aliens.dms.android.core.ui.mvi.UiState import team.aliens.dms.android.data.outing.model.CurrentAppliedOutingApplication import team.aliens.dms.android.data.outing.model.OutingApplicationTime import team.aliens.dms.android.data.outing.repository.OutingRepository +import team.aliens.dms.android.data.student.model.Student +import team.aliens.dms.android.data.student.repository.StudentRepository import team.aliens.dms.android.shared.date.util.now import team.aliens.dms.android.shared.date.util.today +import java.util.UUID import javax.inject.Inject @HiltViewModel class OutingViewModel @Inject constructor( private val outingRepository: OutingRepository, + private val studentRepository: StudentRepository, ) : BaseMviViewModel( initialState = OutingUiState.initial(), ) { @@ -26,6 +30,7 @@ class OutingViewModel @Inject constructor( fetchOutingApplicationTime() fetchCurrentAppliedOutingApplication() fetchOutingTypes() + fetchStudents() } override fun processIntent(intent: OutingIntent) { @@ -35,6 +40,7 @@ class OutingViewModel @Inject constructor( is OutingIntent.UpdateReason -> updateReason(value = intent.value) is OutingIntent.UpdateOutingStartTime -> updateOutingStartTime(value = intent.value) is OutingIntent.UpdateOutingEndTime -> updateOutingEndTime(value = intent.value) + OutingIntent.ApplyOuting -> applyOuting() } } @@ -106,6 +112,43 @@ class OutingViewModel @Inject constructor( selectedOutingEndTime = value, ), ) + + private fun applyOuting() = run { + val capturedState = stateFlow.value + if (capturedState.selectedOutingType == null) { + postSideEffect(OutingSideEffect.OutingTypeNotSelected) + return@run + } + + viewModelScope.launch(Dispatchers.IO) { + runCatching { + /*outingRepository.applyOuting( + date = capturedState.capturedNow.toLocalDate(), + startTime = capturedState.selectedOutingStartTime + ":00", + endTime = capturedState.selectedOutingEndTime + ":00", + type = capturedState.selectedOutingType, + reason = if (capturedState.reason.isBlank()) { + null + } else { + capturedState.reason + }, + companionIds = + )*/ + } + } + } + + private fun fetchStudents() = viewModelScope.launch(Dispatchers.IO) { + runCatching { + studentRepository.fetchStudents() + }.onSuccess { fetchedStudents -> + reduce( + newState = stateFlow.value.copy( + students = fetchedStudents, + ), + ) + } + } } data class OutingUiState( @@ -117,6 +160,8 @@ data class OutingUiState( val capturedNow: LocalDateTime, val selectedOutingStartTime: String, val selectedOutingEndTime: String, + val companionIds: List, + val students: List?, ) : UiState() { companion object { fun initial(): OutingUiState { @@ -131,6 +176,8 @@ data class OutingUiState( // TODO: remove hard-coded string resources from viewmodel selectedOutingEndTime = "${capturedNow.hour}:${capturedNow.minute}", selectedOutingStartTime = "${capturedNow.hour}:${capturedNow.minute}", + companionIds = emptyList(), + students = null, ) } } @@ -142,8 +189,10 @@ sealed class OutingIntent : Intent() { class UpdateReason(val value: String) : OutingIntent() class UpdateOutingStartTime(val value: String) : OutingIntent() class UpdateOutingEndTime(val value: String) : OutingIntent() + data object ApplyOuting : OutingIntent() } sealed class OutingSideEffect : SideEffect() { data object CurrentAppliedOutingApplicationNotFound : OutingSideEffect() + data object OutingTypeNotSelected : OutingSideEffect() } From ec78558e72efc2c46738141b4f6313b5603025e8 Mon Sep 17 00:00:00 2001 From: uielPark Date: Sun, 31 Mar 2024 22:34:55 +0900 Subject: [PATCH 085/129] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20DmsIcon=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/core/designsystem/DmsIcon.kt | 36 +++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/DmsIcon.kt diff --git a/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/DmsIcon.kt b/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/DmsIcon.kt new file mode 100644 index 000000000..aa00d4d6c --- /dev/null +++ b/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/DmsIcon.kt @@ -0,0 +1,36 @@ +package team.aliens.dms.android.core.designsystem + +object DmsIcon { + val Applicate = R.drawable.ic_applicate + val Back = R.drawable.ic_back + val Backward = R.drawable.ic_backward + val Bell = R.drawable.ic_bell + val BlueBreakfast = R.drawable.ic_blue_breakfast + val BlueDinner = R.drawable.ic_blue_dinner + val BlueLaunch = R.drawable.ic_blue_lunch + val Breakfast = R.drawable.ic_breakfast + val Calender = R.drawable.ic_calender + val Camera = R.drawable.ic_camera + val Check = R.drawable.ic_check + val Close = R.drawable.ic_close + val Dinner = R.drawable.ic_dinner + val Down = R.drawable.ic_down + val Forward = R.drawable.ic_forward + val Home = R.drawable.ic_home + val Information = R.drawable.ic_information + val LogoDark = R.drawable.ic_logo_dark + val LogoLight = R.drawable.ic_logo_light + val Lunch = R.drawable.ic_lunch + val MyPage = R.drawable.ic_my_page + val Notice = R.drawable.ic_notice + val Palette = R.drawable.ic_palette + val PasswordInvisible = R.drawable.ic_password_invisible + val PasswordVisible = R.drawable.ic_password_visible + val Photo = R.drawable.ic_photo + val PhotoClose = R.drawable.ic_photo_close + val Plus = R.drawable.ic_plus + val Sort = R.drawable.ic_sort + val Visible = R.drawable.ic_visible + val Warning = R.drawable.ic_warning + val BlueNotice = R.drawable.ic_blue_notice +} \ No newline at end of file From 00d0233616304e7714ca8eed52f5d723c1553b46 Mon Sep 17 00:00:00 2001 From: uielPark Date: Sun, 31 Mar 2024 22:35:50 +0900 Subject: [PATCH 086/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20shape?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/aliens/dms/android/core/designsystem/TextFields.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/TextFields.kt b/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/TextFields.kt index 3a1e7d996..3f0f363c2 100644 --- a/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/TextFields.kt +++ b/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/TextFields.kt @@ -376,7 +376,7 @@ object TextFieldDefaults { ) val shape: Shape - @Composable get() = DmsTheme.shapes.medium + @Composable get() = DmsTheme.shapes.small val MinHeight = 52.dp From ca1fc21fd95068a328ff3241fd5eb7096c54e717 Mon Sep 17 00:00:00 2001 From: uielPark Date: Sun, 31 Mar 2024 22:36:45 +0900 Subject: [PATCH 087/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20name?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../main/res/drawable/{coloricnotice.xml => ic_blue_notice.xml} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename core/design-system/src/main/res/drawable/{coloricnotice.xml => ic_blue_notice.xml} (100%) diff --git a/core/design-system/src/main/res/drawable/coloricnotice.xml b/core/design-system/src/main/res/drawable/ic_blue_notice.xml similarity index 100% rename from core/design-system/src/main/res/drawable/coloricnotice.xml rename to core/design-system/src/main/res/drawable/ic_blue_notice.xml From 529ac34b72904060c1319ea99078146cda7a3b38 Mon Sep 17 00:00:00 2001 From: uielPark Date: Tue, 2 Apr 2024 21:34:38 +0900 Subject: [PATCH 088/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20string?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/src/main/res/values/strings.xml | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index 7b84fd0fa..4cee5f428 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -171,7 +171,13 @@ 로그인 화면으로 + + 이름 + 학년 + + 번호 + 아이디 찾기 %s 으로 아이디가 전송되었습니다 학교를 선택해주세요 From 257c3c77b38bd3712ad67e3566fe5ff5839b1eb9 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Wed, 3 Apr 2024 18:44:22 +0900 Subject: [PATCH 089/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20column=20colo?= =?UTF-8?q?r?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/core/designsystem/Layout.kt | 38 +++++++++++-------- 1 file changed, 23 insertions(+), 15 deletions(-) diff --git a/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Layout.kt b/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Layout.kt index 0bb2878c1..36b9d1c13 100644 --- a/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Layout.kt +++ b/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Layout.kt @@ -24,29 +24,25 @@ import androidx.compose.ui.graphics.Color import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp -private val topFadeBrush: Brush - @Composable inline get() = Brush.verticalGradient( +@Composable +fun VerticallyFadedColumn( + modifier: Modifier = Modifier, + topDisappearanceSize: Dp = 24.dp, + bottomDisappearanceSize: Dp = 24.dp, + verticalArrangement: Arrangement.Vertical = Arrangement.Top, + horizontalAlignment: Alignment.Horizontal = Alignment.Start, + topFadeBrush: Brush = Brush.verticalGradient( colors = listOf( DmsTheme.colorScheme.background, Color.Transparent, ), - ) - -private val bottomFadeBrush: Brush - @Composable inline get() = Brush.verticalGradient( + ), + bottomFadeBrush: Brush = Brush.verticalGradient( colors = listOf( Color.Transparent, DmsTheme.colorScheme.background, ), - ) - -@Composable -fun VerticallyFadedColumn( - modifier: Modifier = Modifier, - topDisappearanceSize: Dp = 24.dp, - bottomDisappearanceSize: Dp = 24.dp, - verticalArrangement: Arrangement.Vertical = Arrangement.Top, - horizontalAlignment: Alignment.Horizontal = Alignment.Start, + ), content: @Composable ColumnScope.() -> Unit, ) { Box( @@ -91,6 +87,18 @@ fun VerticallyFadedLazyColumn( bottomDisappearanceSize: Dp = 24.dp, verticalArrangement: Arrangement.Vertical = if (!reverseLayout) Arrangement.Top else Arrangement.Bottom, horizontalAlignment: Alignment.Horizontal = Alignment.Start, + topFadeBrush: Brush = Brush.verticalGradient( + colors = listOf( + DmsTheme.colorScheme.background, + Color.Transparent, + ), + ), + bottomFadeBrush: Brush = Brush.verticalGradient( + colors = listOf( + Color.Transparent, + DmsTheme.colorScheme.background, + ), + ), content: LazyListScope.() -> Unit, ) { Box( From e106c0b50634ab7819f34ab8b20e45a07e306a93 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Wed, 3 Apr 2024 18:44:28 +0900 Subject: [PATCH 090/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20scre?= =?UTF-8?q?en?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/outing/OutingApplicationScreen.kt | 243 +++++++++++++++++- .../android/feature/outing/OutingViewModel.kt | 72 +++++- 2 files changed, 305 insertions(+), 10 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt index 17fdb9032..a89ff87a7 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt @@ -1,5 +1,6 @@ package team.aliens.dms.android.feature.outing +import androidx.compose.foundation.BorderStroke import androidx.compose.foundation.background import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box @@ -9,25 +10,34 @@ import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height +import androidx.compose.foundation.layout.heightIn import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size +import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Card +import androidx.compose.material3.CardDefaults import androidx.compose.material3.DropdownMenuItem import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ExposedDropdownMenuBox import androidx.compose.material3.ExposedDropdownMenuDefaults import androidx.compose.material3.Icon import androidx.compose.material3.IconButton +import androidx.compose.material3.ModalBottomSheetDefaults import androidx.compose.material3.Text import androidx.compose.material3.TimePicker +import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.material3.rememberTimePickerState import androidx.compose.runtime.Composable import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember +import androidx.compose.runtime.rememberCoroutineScope import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource @@ -35,22 +45,32 @@ import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle +import coil.compose.AsyncImage import com.ramcosta.composedestinations.annotation.Destination +import kotlinx.coroutines.delay +import kotlinx.coroutines.launch import org.threeten.bp.DayOfWeek import team.aliens.dms.android.core.designsystem.AlertDialog import team.aliens.dms.android.core.designsystem.Button import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar +import team.aliens.dms.android.core.designsystem.ModalBottomSheet import team.aliens.dms.android.core.designsystem.Scaffold +import team.aliens.dms.android.core.designsystem.ShadowDefaults import team.aliens.dms.android.core.designsystem.TextButton import team.aliens.dms.android.core.designsystem.TextField +import team.aliens.dms.android.core.designsystem.VerticallyFadedLazyColumn import team.aliens.dms.android.core.ui.DefaultHorizontalSpace import team.aliens.dms.android.core.ui.DefaultVerticalSpace +import team.aliens.dms.android.core.ui.PaddingDefaults import team.aliens.dms.android.core.ui.bottomPadding import team.aliens.dms.android.core.ui.composable.FloatingNotice import team.aliens.dms.android.core.ui.endPadding import team.aliens.dms.android.core.ui.horizontalPadding import team.aliens.dms.android.core.ui.startPadding +import team.aliens.dms.android.core.ui.topPadding +import team.aliens.dms.android.core.ui.verticalPadding +import team.aliens.dms.android.data.student.model.Student import team.aliens.dms.android.feature.R import team.aliens.dms.android.feature.outing.navigation.OutingNavigator @@ -65,13 +85,12 @@ fun OutingApplicationScreen( val (outingTypeMenuExpanded, onChangeOutingTypeMenuExpanded) = remember { mutableStateOf(false) } - + val scope = rememberCoroutineScope() val startTimePickerState = rememberTimePickerState() val (shouldShowStartTimePicker, onChangeShouldShowStartTimePicker) = remember { mutableStateOf(false) } - if (shouldShowStartTimePicker) { AlertDialog( confirmButton = { @@ -81,7 +100,7 @@ fun OutingApplicationScreen( onChangeShouldShowStartTimePicker(false) }, ) { - Text(text = stringResource(id = R.string.close)) + Text(text = stringResource(id = R.string.accept)) } }, onDismissRequest = { onChangeShouldShowStartTimePicker(false) }, @@ -93,7 +112,6 @@ fun OutingApplicationScreen( val (shouldShowEndTimePicker, onChangeShouldShowEndTimePicker) = remember { mutableStateOf(false) } - if (shouldShowEndTimePicker) { AlertDialog( confirmButton = { @@ -111,6 +129,108 @@ fun OutingApplicationScreen( ) } + val (shouldShowCompanionListDialog, onShouldShowCompanionListDialogChange) = remember { + mutableStateOf(false) + } + val sheetState = rememberModalBottomSheetState() + if (shouldShowCompanionListDialog) { + ModalBottomSheet( + sheetState = sheetState, + onDismissRequest = { onShouldShowCompanionListDialogChange(false) }, + properties = ModalBottomSheetDefaults.properties( + shouldDismissOnBackPress = false, + ), + ) { + Column( + modifier = Modifier + .fillMaxWidth() + .heightIn( + max = 640.dp, + ), + ) { + // TODO: 딜레이 서치 + val (studentFilterValue, onStudentFilterValueChange) = remember { mutableStateOf("") } + TextField( + modifier = Modifier + .fillMaxWidth() + .horizontalPadding() + .topPadding(), + hint = { Text(text = stringResource(R.string.outing_application_search_with_number_or_name)) }, + value = studentFilterValue, + onValueChange = onStudentFilterValueChange, + ) + + StudentList( + modifier = Modifier + .fillMaxWidth() + .heightIn(max = 240.dp), + students = uiState.students?.filter { + it.name.contains(studentFilterValue) + || it.gradeClassNumber.contains(studentFilterValue) + }, + selectedStudents = uiState.selectedStudents, + onSelectStudent = { student -> + // TODO: Select를 Pair에 포함시켜서 탐색 시간 단축 + viewModel.postIntent( + OutingIntent.SelectStudent( + student = student, + select = !uiState.selectedStudents.contains(student), + ), + ) + }, + ) + // TODO + Text( + modifier = Modifier + .startPadding() + .topPadding(), + text = stringResource(R.string.outing_application_selected_companions), + style = DmsTheme.typography.caption, + ) + StudentList( + modifier = Modifier + .fillMaxWidth() + .heightIn(max = 240.dp), + students = uiState.selectedStudents, + // TODO: students 파라미터를 List>로 변경하기 + selectedStudents = emptyList(), + onSelectStudent = { student -> + viewModel.postIntent( + OutingIntent.SelectStudent( + student = student, + select = false, + ), + ) + }, + selectedOnly = true, + ) + Button( + modifier = Modifier + .fillMaxWidth() + .horizontalPadding() + .bottomPadding(), + onClick = { + scope.launch { + sheetState.hide() + onShouldShowCompanionListDialogChange(false) + } + }, + ) { + Text( + text = if (uiState.selectedStudents.isEmpty()) { + stringResource(id = R.string.close) + } else { + stringResource( + id = R.string.outing_format_select_companions, + uiState.selectedStudents.size, + ) + }, + ) + } + } + } + } + Scaffold( topBar = { DmsTopAppBar( @@ -208,8 +328,8 @@ fun OutingApplicationScreen( }, value = stringResource( id = R.string.outing_format_duration_h_m, - time[0].toInt(), - time[1].toInt(), + time[0], + time[1], ), onValueChange = {}, readOnly = true, @@ -313,7 +433,9 @@ fun OutingApplicationScreen( onValueChange = { /* explicit blank */ }, readOnly = true, trailingIcon = { - IconButton(onClick = { /*TODO*/ }) { + IconButton( + onClick = { onShouldShowCompanionListDialogChange(true) }, + ) { Icon( painter = painterResource(id = team.aliens.dms.android.core.designsystem.R.drawable.ic_plus), contentDescription = stringResource(id = R.string.outing_add_companions), @@ -343,8 +465,7 @@ fun OutingApplicationScreen( Button( modifier = Modifier .fillMaxWidth() - .startPadding() - .endPadding() + .horizontalPadding() .bottomPadding(), onClick = { /*TODO*/ }, ) { @@ -354,6 +475,110 @@ fun OutingApplicationScreen( } } +@Composable +private fun StudentList( + modifier: Modifier = Modifier, + students: List?, + selectedStudents: List, + selectedOnly: Boolean = false, + onSelectStudent: (Student) -> Unit, +) { + VerticallyFadedLazyColumn( + modifier = modifier, + topFadeBrush = Brush.verticalGradient( + colors = listOf( + DmsTheme.colorScheme.surface, + Color.Transparent, + ), + ), + bottomFadeBrush = Brush.verticalGradient( + colors = listOf( + Color.Transparent, + DmsTheme.colorScheme.surface, + ), + ), + verticalArrangement = Arrangement.spacedBy(DefaultVerticalSpace), + ) { + if (students != null) { + items(students) { student -> + val selected = if (selectedOnly) { + true + } else { + selectedStudents.any { it == student } + }/* + AnimatedVisibility( + visible = selected, + enter = fadeIn(), + exit = slideOutFromStart(), + ) {*/ + StudentCard( + modifier = Modifier + .fillMaxWidth() + .horizontalPadding(), + student = student, + selected = selected, + onClick = onSelectStudent, + ) + } + } + } +} + +@Composable +private fun StudentCard( + modifier: Modifier = Modifier, + student: Student, + selected: Boolean, + onClick: (Student) -> Unit, +) { + Card( + modifier = modifier.verticalPadding(PaddingDefaults.ExtraSmall), + shape = DmsTheme.shapes.surfaceSmall, + colors = CardDefaults.cardColors( + containerColor = DmsTheme.colorScheme.surface, + contentColor = DmsTheme.colorScheme.onSurface, + ), + border = if (selected) { + BorderStroke( + width = 1.dp, + color = DmsTheme.colorScheme.primary, + ) + } else { + null + }, + elevation = CardDefaults.cardElevation(defaultElevation = ShadowDefaults.SmallElevation), + onClick = { onClick(student) }, + ) { + Row( + modifier = Modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, + ) { + AsyncImage( + modifier = Modifier + .startPadding() + .topPadding() + .bottomPadding() + .size(48.dp) + .clip(CircleShape), + model = student.profileImageUrl, + contentDescription = null, + ) + Spacer(modifier = Modifier.weight(1f)) + Text( + modifier = Modifier + .topPadding() + .endPadding() + .bottomPadding(), + text = stringResource( + id = R.string.outing_application_format_grade_class_number_with_name, + student.gradeClassNumber, + student.name, + ), + ) + } + } +} + @Composable private fun OutingInput( modifier: Modifier = Modifier, diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt index e6afa429e..1745c7650 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt @@ -41,6 +41,10 @@ class OutingViewModel @Inject constructor( is OutingIntent.UpdateOutingStartTime -> updateOutingStartTime(value = intent.value) is OutingIntent.UpdateOutingEndTime -> updateOutingEndTime(value = intent.value) OutingIntent.ApplyOuting -> applyOuting() + is OutingIntent.SelectStudent -> selectStudent( + student = intent.student, + select = intent.select, + ) } } @@ -140,8 +144,48 @@ class OutingViewModel @Inject constructor( private fun fetchStudents() = viewModelScope.launch(Dispatchers.IO) { runCatching { - studentRepository.fetchStudents() + // FIXME + // studentRepository.fetchStudents() + listOf( + Student( + id = UUID.randomUUID(), + name = "박준수", + gradeClassNumber = "3211", + profileImageUrl = "www.naver.com", + ), + Student( + id = UUID.randomUUID(), + name = "준박수", + gradeClassNumber = "1234", + profileImageUrl = "www.naver.com", + ), + Student( + id = UUID.randomUUID(), + name = "박준혁", + gradeClassNumber = "2211", + profileImageUrl = "www.naver.com", + ), + Student( + id = UUID.randomUUID(), + name = "수준봐", + gradeClassNumber = "1111", + profileImageUrl = "www.naver.com", + ), + Student( + id = UUID.randomUUID(), + name = "코딱지", + gradeClassNumber = "4411", + profileImageUrl = "www.naver.com", + ), + Student( + id = UUID.randomUUID(), + name = "빅준자", + gradeClassNumber = "9213", + profileImageUrl = "www.naver.com", + ), + ) }.onSuccess { fetchedStudents -> + println(fetchedStudents) reduce( newState = stateFlow.value.copy( students = fetchedStudents, @@ -149,6 +193,26 @@ class OutingViewModel @Inject constructor( ) } } + + private fun selectStudent( + student: Student, + select: Boolean, + ) = run { + val capturedState = stateFlow.value + reduce( + newState = capturedState.copy( + selectedStudents = if (select) { + capturedState.selectedStudents.toMutableList().apply { + add(student) + } + } else { + capturedState.selectedStudents.toMutableList().apply { + remove(student) + } + }, + ) + ) + } } data class OutingUiState( @@ -162,6 +226,7 @@ data class OutingUiState( val selectedOutingEndTime: String, val companionIds: List, val students: List?, + val selectedStudents: List, ) : UiState() { companion object { fun initial(): OutingUiState { @@ -178,6 +243,7 @@ data class OutingUiState( selectedOutingStartTime = "${capturedNow.hour}:${capturedNow.minute}", companionIds = emptyList(), students = null, + selectedStudents = emptyList(), ) } } @@ -190,6 +256,10 @@ sealed class OutingIntent : Intent() { class UpdateOutingStartTime(val value: String) : OutingIntent() class UpdateOutingEndTime(val value: String) : OutingIntent() data object ApplyOuting : OutingIntent() + class SelectStudent( + val student: Student, + val select: Boolean, + ) : OutingIntent() } sealed class OutingSideEffect : SideEffect() { From 998592ad5881b916ad26b7ffdc654858342b46c8 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Wed, 3 Apr 2024 18:44:36 +0900 Subject: [PATCH 091/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20student=20mod?= =?UTF-8?q?el?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/aliens/dms/android/data/student/model/Student.kt | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/student/model/Student.kt b/data/src/main/java/team/aliens/dms/android/data/student/model/Student.kt index 4f4781939..d32bfde24 100644 --- a/data/src/main/java/team/aliens/dms/android/data/student/model/Student.kt +++ b/data/src/main/java/team/aliens/dms/android/data/student/model/Student.kt @@ -1,9 +1,10 @@ package team.aliens.dms.android.data.student.model import team.aliens.dms.android.network.student.model.FetchStudentsResponse +import java.util.UUID data class Student( - val id: String, + val id: UUID, val name: String, val gradeClassNumber: String, val profileImageUrl: String, @@ -13,7 +14,7 @@ fun FetchStudentsResponse.toModel(): List = this.students.map(FetchStudentsResponse.StudentResponse::toModel) fun FetchStudentsResponse.StudentResponse.toModel(): Student = Student( - id = this.id, + id = UUID.fromString(this.id), name = this.name, gradeClassNumber = this.gradeClassNumber, profileImageUrl = this.profileImageUrl, From f329514ce15d5f10157b45a8b18f0e0d74d12705 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Wed, 3 Apr 2024 18:44:40 +0900 Subject: [PATCH 092/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20string=20mode?= =?UTF-8?q?l?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/src/main/res/values/strings.xml | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index 31bd39e0c..178eed307 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -311,5 +311,9 @@ %04d.%02d.%02d (%s) 외출 시간 복귀 시간 - 내용을 입력해 주세요 + 외출 사유를 입력해 주세요 + %d명 선택 + 학번/이름으로 검색해 보세요 + 선택한 학생 + %s %s \ No newline at end of file From d280825600de2cd77ad139c1cd3145c941388e5c Mon Sep 17 00:00:00 2001 From: junsuPark Date: Wed, 3 Apr 2024 18:53:38 +0900 Subject: [PATCH 093/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20Outing?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/outing/OutingApplicationScreen.kt | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt index a89ff87a7..b9285e892 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt @@ -29,6 +29,8 @@ import androidx.compose.material3.TimePicker import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.material3.rememberTimePickerState import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect +import androidx.compose.runtime.DisposableEffectResult import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -47,7 +49,6 @@ import androidx.compose.ui.unit.dp import androidx.lifecycle.compose.collectAsStateWithLifecycle import coil.compose.AsyncImage import com.ramcosta.composedestinations.annotation.Destination -import kotlinx.coroutines.delay import kotlinx.coroutines.launch import org.threeten.bp.DayOfWeek import team.aliens.dms.android.core.designsystem.AlertDialog @@ -429,7 +430,18 @@ fun OutingApplicationScreen( text = { Text(text = stringResource(id = R.string.outing_companion_names)) }, ) { TextField( - value = stringResource(id = R.string.outing_add_companions), + value = if (uiState.selectedStudents.isEmpty()) { + stringResource(id = R.string.outing_add_companions) + } else { + StringBuilder().apply { + uiState.selectedStudents.forEachIndexed { index, student -> + this.append("${student.gradeClassNumber} ${student.name} ") + if (index != uiState.selectedStudents.lastIndex) { + this.append(',') + } + } + }.toString() + }, onValueChange = { /* explicit blank */ }, readOnly = true, trailingIcon = { @@ -558,7 +570,7 @@ private fun StudentCard( .startPadding() .topPadding() .bottomPadding() - .size(48.dp) + .size(24.dp) .clip(CircleShape), model = student.profileImageUrl, contentDescription = null, From 174a058570168ce250f7aab3c8deb01a1843b01e Mon Sep 17 00:00:00 2001 From: uielPark Date: Fri, 5 Apr 2024 19:53:17 +0900 Subject: [PATCH 094/129] =?UTF-8?q?=F0=9F=93=91=20::=20mapper?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/data/school/mapper/SchoolMapper.kt | 13 +++++++++++++ 1 file changed, 13 insertions(+) create mode 100644 data/src/main/java/team/aliens/dms/android/data/school/mapper/SchoolMapper.kt diff --git a/data/src/main/java/team/aliens/dms/android/data/school/mapper/SchoolMapper.kt b/data/src/main/java/team/aliens/dms/android/data/school/mapper/SchoolMapper.kt new file mode 100644 index 000000000..78708c6af --- /dev/null +++ b/data/src/main/java/team/aliens/dms/android/data/school/mapper/SchoolMapper.kt @@ -0,0 +1,13 @@ +package team.aliens.dms.android.data.school.mapper + +import team.aliens.dms.android.data.school.model.School +import team.aliens.dms.android.network.school.model.FetchSchoolsResponse + +fun FetchSchoolsResponse.toModel(): List = + this.schools.map(FetchSchoolsResponse.SchoolResponse::toModel) + +private fun FetchSchoolsResponse.SchoolResponse.toModel(): School = School( + id = this.id, + name = this.name, + address = this.address, +) From b1768b04f3cb31f0e7190f97b22b298f9e52d105 Mon Sep 17 00:00:00 2001 From: uielPark Date: Fri, 5 Apr 2024 19:54:34 +0900 Subject: [PATCH 095/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20SchoolReposit?= =?UTF-8?q?oryImpl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/data/school/repository/SchoolRepositoryImpl.kt | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/school/repository/SchoolRepositoryImpl.kt b/data/src/main/java/team/aliens/dms/android/data/school/repository/SchoolRepositoryImpl.kt index 9bfa66ac4..5be517748 100644 --- a/data/src/main/java/team/aliens/dms/android/data/school/repository/SchoolRepositoryImpl.kt +++ b/data/src/main/java/team/aliens/dms/android/data/school/repository/SchoolRepositoryImpl.kt @@ -1,5 +1,6 @@ package team.aliens.dms.android.data.school.repository +import team.aliens.dms.android.data.school.mapper.toModel import team.aliens.dms.android.data.school.model.School import team.aliens.dms.android.data.school.model.SchoolId import team.aliens.dms.android.data.school.model.SchoolVerificationQuestion @@ -11,9 +12,8 @@ internal class SchoolRepositoryImpl @Inject constructor( private val networkSchoolDataSource: NetworkSchoolDataSource, ) : SchoolRepository() { - override suspend fun fetchSchools(): List { - TODO("Not yet implemented") - } + override suspend fun fetchSchools(): List = + networkSchoolDataSource.fetchSchools().toModel() override suspend fun fetchSchoolVerificationQuestion(schoolId: UUID): SchoolVerificationQuestion = networkSchoolDataSource.fetchSchoolVerificationQuestion(schoolId = schoolId).question From 0805c4c5cb2fc32e623dd60acb5bf07733a9caaa Mon Sep 17 00:00:00 2001 From: uielPark Date: Fri, 5 Apr 2024 19:55:06 +0900 Subject: [PATCH 096/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20StudentReposi?= =?UTF-8?q?toryImpl?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/student/repository/StudentRepositoryImpl.kt | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt b/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt index a32338de3..9915bf43d 100644 --- a/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt +++ b/data/src/main/java/team/aliens/dms/android/data/student/repository/StudentRepositoryImpl.kt @@ -6,7 +6,6 @@ import team.aliens.dms.android.data.student.mapper.toModel import team.aliens.dms.android.data.student.model.HashedEmail import team.aliens.dms.android.data.student.model.MyPage import team.aliens.dms.android.data.student.model.StudentName -import team.aliens.dms.android.network.auth.datasource.NetworkAuthDataSource import team.aliens.dms.android.network.student.datasource.NetworkStudentDataSource import team.aliens.dms.android.network.student.model.ResetPasswordRequest import team.aliens.dms.android.network.student.model.SignUpRequest @@ -73,9 +72,14 @@ internal class StudentRepositoryImpl @Inject constructor( grade: Int, classRoom: Int, number: Int, - ): HashedEmail { - TODO("Not yet implemented") - } + ): HashedEmail = + networkStudentDataSource.findId( + schoolId = schoolId, + studentName = studentName, + grade = grade, + classRoom = classRoom, + number = number, + ).email override suspend fun resetPassword( accountId: String, From 99acdf24cbd17d6e294db1321d1a3dfa13f6b697 Mon Sep 17 00:00:00 2001 From: uielPark Date: Fri, 5 Apr 2024 19:55:38 +0900 Subject: [PATCH 097/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20findIdScreen?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/findid/FindIdScreen.kt | 428 ++++++++++-------- 1 file changed, 227 insertions(+), 201 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdScreen.kt index cff257bdb..febe48de9 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdScreen.kt @@ -1,236 +1,262 @@ package team.aliens.dms.android.feature.findid +import android.annotation.SuppressLint +import androidx.compose.foundation.layout.Arrangement +import androidx.compose.foundation.layout.Box +import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.PaddingValues +import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer +import androidx.compose.foundation.layout.fillMaxSize +import androidx.compose.foundation.layout.fillMaxWidth +import androidx.compose.foundation.layout.imePadding +import androidx.compose.foundation.layout.padding +import androidx.compose.foundation.text.KeyboardOptions +import androidx.compose.material3.DropdownMenu +import androidx.compose.material3.DropdownMenuItem +import androidx.compose.material3.ExperimentalMaterial3Api +import androidx.compose.material3.Icon +import androidx.compose.material3.IconButton +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +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.focus.FocusRequester +import androidx.compose.ui.focus.focusRequester +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.res.painterResource +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.text.input.ImeAction +import androidx.compose.ui.text.input.KeyboardType +import androidx.compose.ui.unit.dp +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination +import team.aliens.dms.android.core.designsystem.AlertDialog +import team.aliens.dms.android.core.designsystem.Button +import team.aliens.dms.android.core.designsystem.ContainedButton +import team.aliens.dms.android.core.designsystem.DmsIcon +import team.aliens.dms.android.core.designsystem.DmsScaffold +import team.aliens.dms.android.core.designsystem.DmsTopAppBar +import team.aliens.dms.android.core.designsystem.LocalToast +import team.aliens.dms.android.core.designsystem.TextField +import team.aliens.dms.android.core.designsystem.clickable +import team.aliens.dms.android.core.ui.Banner +import team.aliens.dms.android.core.ui.BannerDefaults +import team.aliens.dms.android.core.ui.DefaultHorizontalSpace +import team.aliens.dms.android.core.ui.DefaultVerticalSpace +import team.aliens.dms.android.core.ui.bottomPadding +import team.aliens.dms.android.core.ui.collectInLaunchedEffectWithLifecycle +import team.aliens.dms.android.core.ui.horizontalPadding +import team.aliens.dms.android.core.ui.topPadding +import team.aliens.dms.android.feature.R import team.aliens.dms.android.feature.findid.navigator.FindIdNavigator +@SuppressLint("StateFlowValueCalledInComposition") +@OptIn(ExperimentalMaterial3Api::class) @Destination @Composable -fun FindIdScreen( - modifier: Modifier = Modifier, +internal fun FindIdScreen( navigator: FindIdNavigator, - // findIdViewModel: FindIdViewModel = hiltViewModel(), -) {/* - - val focusManager = LocalFocusManager.current - - var nameState by remember { mutableStateOf("") } - var gradeState by remember { mutableStateOf("") } - var classRoomState by remember { mutableStateOf("") } - var numberState by remember { mutableStateOf("") } - var findIdDialogState by remember { mutableStateOf(false) } - var errorState by remember { mutableStateOf(false) } - - var isDropdownMenuExpanded by remember { mutableStateOf(false) } - var schoolList = remember { - mutableStateListOf() - } + viewModel: FindIdViewModel = hiltViewModel(), +) { + val uiState by viewModel.stateFlow.collectAsStateWithLifecycle() + val toast = LocalToast.current + val context = LocalContext.current + var isDialogShow by remember { mutableStateOf(false) } - var selectedSchool by remember { - mutableStateOf( - FetchSchoolsOutput.SchoolInformation( - name = "", - address = "", - ), + if (isDialogShow) { + AlertDialog( + text = { + Text( + text = String.format( + stringResource(id = R.string.find_id_send_id_to_email), + uiState.email + ) + ) + }, + onDismissRequest = { /* explicit blank */ }, + confirmButton = { + Button( + modifier = Modifier.fillMaxWidth(), + onClick = navigator::navigateUp, + ) { + Text(text = stringResource(id = R.string.find_id_go_to_login_screen)) + } + }, ) } - val toast = rememberToast() - val context = LocalContext.current + viewModel.sideEffectFlow.collectInLaunchedEffectWithLifecycle { sideEffect -> + when (sideEffect) { + FindIdSideEffect.Success -> { + isDialogShow = true + } - if (findIdDialogState) { - DormCustomDialog( - onDismissRequest = {}, - ) { - DormSingleButtonDialog( - content = stringResource(id = R.string.SendIdToEmail, findIdViewModel.email), - mainBtnText = stringResource(id = R.string.GoLoginScreen), - onMainBtnClick = navigator::popBackStack, - mainBtnTextColor = DormTheme.colors.primary, - ) + FindIdSideEffect.NotFound -> toast.showErrorToast(context.getString(R.string.error_not_found)) } } - LaunchedEffect(Unit) { - findIdViewModel.findIdEvent.collect { event -> - when (event) { - is FetchSchools -> { - schoolList.addAll(event.fetchSchoolsOutput.schools) - } - - SuccessFindId -> { - findIdDialogState = true - } - - FindIdNoInternetException -> { - toast(context.getString(R.string.NoInternetException)) - } - - FindIdServerException -> { - toast(context.getString(R.string.ServerException)) - } - - FindIdTooManyRequest -> { - toast(context.getString(R.string.TooManyRequest)) - } - - FindIdUnknownException -> { - toast(context.getString(R.string.UnKnownException)) - } - - FindIdNeedLoginException -> { - toast(context.getString(R.string.NeedAccount)) - } - - FindIdBadRequest -> { - toast(context.getString(R.string.BadRequest)) - } - - FindIdNotFound -> { - toast(context.getString(R.string.ChangePasswordNotFound)) - } - - FindIdUnauthorized -> { - toast(context.getString(R.string.MissMatchAccountInfo)) + DmsScaffold( + modifier = Modifier.fillMaxSize(), + topBar = { + DmsTopAppBar( + title = { /* explicit blank */ }, + navigationIcon = { + IconButton(onClick = navigator::navigateUp) { + Icon( + painter = painterResource(id = R.drawable.ic_baseline_arrow_back_24), + contentDescription = stringResource(id = R.string.top_bar_back_button), + ) + } + }, + ) + } + ) { paddingValues -> + Column( + modifier = Modifier + .fillMaxSize() + .padding(paddingValues) + .horizontalPadding() + .imePadding() + ) { + Banner( + modifier = Modifier + .fillMaxWidth() + .topPadding(BannerDefaults.DefaultTopSpace), + message = { + Text(text = stringResource(id = R.string.find_id)) } + ) + Spacer(modifier = Modifier.weight(1f)) + UserInformationInputs( + state = uiState, + viewModel = viewModel, + ) + Spacer(modifier = Modifier.weight(2f)) + ContainedButton( + modifier = Modifier + .fillMaxWidth() + .bottomPadding(), + onClick = viewModel::onButtonClick, + enabled = uiState.buttonEnabled, + ) { + Text(text = stringResource(id = R.string.find_id)) } } } +} - Column( // todo refactor - modifier = modifier - .fillMaxSize() - .padding( - top = 16.dp, - start = 16.dp, - end = 16.dp, - ) - .dormClickable( - rippleEnabled = false, - ) { - focusManager.clearFocus() - } +@Composable +private fun UserInformationInputs( + state: FindIdUiState, + viewModel: FindIdViewModel, +) { + val classFocusRequest = remember { FocusRequester() } + val numberFocusRequest = remember { FocusRequester() } + var isDropdownMenuExpanded by remember { mutableStateOf(false) } + + Column( + verticalArrangement = Arrangement.spacedBy(DefaultVerticalSpace) ) { - Space(space = 92.dp) - FindIdHeader() - Space(space = 60.dp) - Column( - modifier = Modifier - .fillMaxWidth() - .wrapContentHeight() - ) { - Box() { - Row( - modifier = Modifier - .clip(MaterialTheme.shapes.small) - .height(46.dp) - .fillMaxWidth() - .clickable { - isDropdownMenuExpanded = !isDropdownMenuExpanded - } - .border( - width = 1.dp, - shape = MaterialTheme.shapes.small, - color = DormTheme.colors.primaryVariant, + Box { + TextField( + modifier = Modifier.clickable( + onClick = { isDropdownMenuExpanded = !isDropdownMenuExpanded } + ), + value = state.schoolName, + onValueChange = { }, + readOnly = true, + hint = { Text(text = stringResource(id = R.string.find_id_select_school)) }, + trailingIcon = { + IconButton(onClick = { isDropdownMenuExpanded = !isDropdownMenuExpanded }) { + Icon( + painter = if (isDropdownMenuExpanded) painterResource(id = com.google.android.material.R.drawable.material_ic_menu_arrow_up_black_24dp) + else painterResource(id = DmsIcon.Down), + contentDescription = "down_icon", ) - - .padding(start = 16.dp, end = 12.dp), - verticalAlignment = Alignment.CenterVertically, - horizontalArrangement = Arrangement.SpaceBetween - ) { - Body2( - text = selectedSchool.name, - color = DormTheme.colors.primaryVariant, - ) - Icon( - painterResource(id = team.aliens.dms.android.designsystem.R.drawable.ic_down), - contentDescription = null, - ) - } - - DropdownMenu( - expanded = isDropdownMenuExpanded, - onDismissRequest = { isDropdownMenuExpanded = false }, - ) { - schoolList.forEach { item -> - DropdownMenuItem( - onClick = { - isDropdownMenuExpanded = false - selectedSchool = item - } - ) { - Text(item.name) - } } } - } - - Space(space = 37.dp) - DormTextField( - value = nameState, - onValueChange = { name -> nameState = name }, - hint = stringResource(id = R.string.Name), - imeAction = ImeAction.Next ) - Space(space = 37.dp) - Row( + DropdownMenu( modifier = Modifier - .fillMaxWidth() - .wrapContentHeight(), - horizontalArrangement = Arrangement.SpaceBetween + .fillMaxWidth(), + expanded = isDropdownMenuExpanded, + onDismissRequest = { isDropdownMenuExpanded = false }, ) { - DormTextField( - modifier = Modifier.width(100.dp), - value = gradeState, - onValueChange = { grade -> gradeState = grade }, - hint = stringResource(id = R.string.Grade), - keyboardType = KeyboardType.NumberPassword, - imeAction = ImeAction.Next, - error = errorState - ) - DormTextField( - modifier = Modifier.width(100.dp), - value = classRoomState, - onValueChange = { classRoom -> classRoomState = classRoom }, - hint = stringResource(id = R.string.ClassRoom), - error = errorState, - keyboardType = KeyboardType.NumberPassword, - imeAction = ImeAction.Next - ) - DormTextField( - modifier = Modifier.width(100.dp), - value = numberState, - onValueChange = { number -> numberState = number }, - hint = stringResource(id = R.string.Number), - keyboardType = KeyboardType.NumberPassword, - error = errorState, - keyboardActions = KeyboardActions { - focusManager.clearFocus() - }, - imeAction = ImeAction.Done, - ) + state.schoolList.forEach { item -> + DropdownMenuItem( + text = { Text(text = item.name) }, + onClick = { + viewModel.postIntent( + FindIdIntent.UpdateSchoolId( + schoolId = item.id, + schoolName = item.name, + ) + ) + isDropdownMenuExpanded = false + }, + contentPadding = PaddingValues(horizontal = 16.dp), + ) + } } } - - Column( - modifier = Modifier - .fillMaxHeight(0.81f), - verticalArrangement = Arrangement.Bottom, + TextField( + value = state.name, + onValueChange = { name -> + viewModel.postIntent(FindIdIntent.UpdateName(name)) + }, + hint = { Text(text = stringResource(id = R.string.find_id_name)) } + ) + Row( + horizontalArrangement = Arrangement.spacedBy(DefaultHorizontalSpace) ) { - DormContainedLargeButton( - text = stringResource(id = R.string.FindId), - color = DormButtonColor.Blue, - enabled = nameState.isNotEmpty() && gradeState.isNotEmpty() && classRoomState.isNotEmpty() && numberState.isNotEmpty() - ) { - findIdViewModel.findId( - schoolId = selectedSchool.id ?: throw IllegalStateException(), - name = nameState, - grade = gradeState.toInt(), - classRoom = classRoomState.toInt(), - number = numberState.toInt(), - ) - } + TextField( + modifier = Modifier + .weight(1f), + value = state.grade, + onValueChange = { grade -> + viewModel.postIntent(FindIdIntent.UpdateGrade(grade)) + if (grade.isNotEmpty()) classFocusRequest.requestFocus() + }, + hint = { Text(text = stringResource(id = R.string.find_id_grade)) }, + keyboardOptions = KeyboardOptions( + imeAction = ImeAction.Next, + keyboardType = KeyboardType.Number, + ), + ) + TextField( + modifier = Modifier + .weight(1f) + .focusRequester(classFocusRequest), + value = state.classRoom, + onValueChange = { classRoom -> + viewModel.postIntent(FindIdIntent.UpdateClass(classRoom)) + if (classRoom.isNotEmpty()) numberFocusRequest.requestFocus() + }, + hint = { Text(text = stringResource(id = R.string.find_id_class)) }, + keyboardOptions = KeyboardOptions( + imeAction = ImeAction.Next, + keyboardType = KeyboardType.Number, + ), + ) + TextField( + modifier = Modifier + .weight(1f) + .focusRequester(numberFocusRequest), + value = state.number, + onValueChange = { number -> + viewModel.postIntent(FindIdIntent.UpdateNumber(number)) + }, + hint = { Text(text = stringResource(id = R.string.find_id_number)) }, + keyboardOptions = KeyboardOptions( + imeAction = ImeAction.Next, + keyboardType = KeyboardType.Number, + ), + ) } - }*/ + } } From 62d583e08c3037ce5246894223eb77ad091807d4 Mon Sep 17 00:00:00 2001 From: uielPark Date: Fri, 5 Apr 2024 19:56:28 +0900 Subject: [PATCH 098/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20view=20model?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/findid/FindIdViewModel.kt | 180 +++++++++++------- 1 file changed, 114 insertions(+), 66 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdViewModel.kt index 039916d2c..41f3e6942 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdViewModel.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdViewModel.kt @@ -1,102 +1,150 @@ package team.aliens.dms.android.feature.findid -/* -import androidx.lifecycle.ViewModel + import androidx.lifecycle.viewModelScope import dagger.hilt.android.lifecycle.HiltViewModel -import java.util.UUID import kotlinx.coroutines.Dispatchers import kotlinx.coroutines.launch -import team.aliens.dms.android.domain.model.school.FetchSchoolsOutput -import team.aliens.dms.android.feature._legacy.util.MutableEventFlow -import team.aliens.dms.android.feature._legacy.util.asEventFlow -import team.aliens.dms.android.domain.model.student.FindIdInput -import team.aliens.dms.android.domain.usecase.school.FetchSchoolsUseCase -import team.aliens.dms.android.domain.usecase.student.FindIdUseCase +import team.aliens.dms.android.core.ui.mvi.BaseMviViewModel +import team.aliens.dms.android.core.ui.mvi.Intent +import team.aliens.dms.android.core.ui.mvi.SideEffect +import team.aliens.dms.android.core.ui.mvi.UiState +import team.aliens.dms.android.data.school.model.School +import team.aliens.dms.android.data.school.repository.SchoolRepository +import team.aliens.dms.android.data.student.repository.StudentRepository +import java.util.UUID import javax.inject.Inject @HiltViewModel -class FindIdViewModel @Inject constructor( - private val findIdUseCase: FindIdUseCase, - private val fetchSchoolsUseCase: FetchSchoolsUseCase, -) : ViewModel() { +internal class FindIdViewModel @Inject constructor( + private val studentRepository: StudentRepository, + private val schoolRepository: SchoolRepository, +) : BaseMviViewModel( + initialState = FindIdUiState.initial(), +) { init { fetchSchools() } - private val _findIdEvent = MutableEventFlow() - internal val findIdEvent = _findIdEvent.asEventFlow() + override fun processIntent(intent: FindIdIntent) { + when (intent) { + is FindIdIntent.UpdateSchoolId -> this.updateSchoolId( + schoolId = intent.schoolId, + schoolName = intent.schoolName + ) + + is FindIdIntent.UpdateName -> this.updateName(name = intent.value) + is FindIdIntent.UpdateGrade -> this.updateGrade(grade = intent.value) + is FindIdIntent.UpdateClass -> this.updateClassRoom(classRoom = intent.value) + is FindIdIntent.UpdateNumber -> this.updateNumber(number = intent.value) + } + } + + private fun updateSchoolId(schoolId: UUID, schoolName: String): Boolean = reduce( + newState = stateFlow.value.copy(schoolId = schoolId, schoolName = schoolName) + ).also { updateButtonEnable(checkInAvailable()) } + + private fun updateName(name: String): Boolean = reduce( + newState = stateFlow.value.copy(name = name) + ).also { updateButtonEnable(checkInAvailable()) } + + private fun updateGrade(grade: String): Boolean = reduce( + newState = stateFlow.value.copy(grade = grade) + ).also { updateButtonEnable(checkInAvailable()) } + + private fun updateClassRoom(classRoom: String): Boolean = reduce( + newState = stateFlow.value.copy(classRoom = classRoom) + ).also { updateButtonEnable(checkInAvailable()) } - lateinit var email: String + private fun updateNumber(number: String): Boolean = reduce( + newState = stateFlow.value.copy(number = number) + ).also { updateButtonEnable(checkInAvailable()) } - internal fun findId(schoolId: UUID, name: String, grade: Int, classRoom: Int, number: Int) { - viewModelScope.launch { - kotlin.runCatching { - email = findIdUseCase( - FindIdInput( + private fun updateButtonEnable(buttonEnabled: Boolean): Boolean = + reduce(newState = stateFlow.value.copy(buttonEnabled = buttonEnabled)) + + private fun checkInAvailable(): Boolean { + val uiState = stateFlow.value + + val nameEntered = uiState.name.isNotBlank() + val gradeEntered = uiState.grade.isNotBlank() + val classRoomEntered = uiState.classRoom.isNotBlank() + val numberEntered = uiState.number.isNotBlank() + + return nameEntered && gradeEntered && classRoomEntered && numberEntered + } + + internal fun onButtonClick() { + with(stateFlow.value) { + viewModelScope.launch(Dispatchers.IO) { + runCatching { + studentRepository.findId( schoolId = schoolId, studentName = name, - grade = grade, - classRoom = classRoom, - number = number, - ), - ).email - }.onSuccess { - event(SuccessFindId) - }.onFailure { - event( - getEventFromThrowable(it), - ) + grade = grade.toInt(), + classRoom = classRoom.toInt(), + number = number.toInt(), + ) + }.onSuccess { email -> + reduce(newState = stateFlow.value.copy(email = email)) + postSideEffect(FindIdSideEffect.Success) + }.onFailure { + postSideEffect(FindIdSideEffect.NotFound) + } } } } private fun fetchSchools() { viewModelScope.launch(Dispatchers.IO) { - kotlin.runCatching { - fetchSchoolsUseCase() + runCatching { + schoolRepository.fetchSchools() }.onSuccess { - event(FetchSchools(it)) + reduce(newState = stateFlow.value.copy(schoolList = it)) }.onFailure { - + postSideEffect(FindIdSideEffect.NotFound) } } } +} - fun event(event: FindIdEvent) { - viewModelScope.launch { - _findIdEvent.emit(event) - } +internal data class FindIdUiState( + val schoolList: List, + val email: String, + val schoolId: UUID, + val schoolName: String, + val name: String, + val grade: String, + val classRoom: String, + val number: String, + val buttonEnabled: Boolean +) : UiState() { + companion object { + fun initial() = FindIdUiState( + schoolList = emptyList(), + email = "", + schoolId = UUID.randomUUID(), + schoolName = "", + name = "", + grade = "", + classRoom = "", + number = "", + buttonEnabled = false, + ) } } -private fun getEventFromThrowable(throwable: Throwable): FindIdEvent { - return when (throwable) { - else -> FindIdUnknownException - } +internal sealed class FindIdIntent : Intent() { + class UpdateSchoolId(val schoolId: UUID, val schoolName: String) : FindIdIntent() + class UpdateName(val value: String) : FindIdIntent() + class UpdateGrade(val value: String) : FindIdIntent() + class UpdateClass(val value: String) : FindIdIntent() + class UpdateNumber(val value: String) : FindIdIntent() } - -sealed interface FindIdEvent - -class FetchSchools(val fetchSchoolsOutput: FetchSchoolsOutput) : FindIdEvent - -object SuccessFindId : FindIdEvent - -object FindIdBadRequest : FindIdEvent - -object FindIdUnauthorized : FindIdEvent - -object FindIdNotFound : FindIdEvent - -object FindIdTooManyRequest : FindIdEvent - -object FindIdServerException : FindIdEvent - -object FindIdNoInternetException : FindIdEvent - -object FindIdNeedLoginException : FindIdEvent - -object FindIdUnknownException : FindIdEvent*/ +internal sealed class FindIdSideEffect : SideEffect() { + data object Success : FindIdSideEffect() + data object NotFound : FindIdSideEffect() +} From 75753d5cd6008094ea591d72eaec0c53c28eff4e Mon Sep 17 00:00:00 2001 From: uielPark Date: Tue, 9 Apr 2024 08:24:15 +0900 Subject: [PATCH 099/129] =?UTF-8?q?=E2=9A=A1=EF=B8=8F=20::=20icon=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aliens/dms/android/core/designsystem/DmsIcon.kt | 1 + core/design-system/src/main/res/drawable/ic_up.xml | 9 +++++++++ .../aliens/dms/android/feature/findid/FindIdScreen.kt | 11 ++++++++--- 3 files changed, 18 insertions(+), 3 deletions(-) create mode 100644 core/design-system/src/main/res/drawable/ic_up.xml diff --git a/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/DmsIcon.kt b/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/DmsIcon.kt index aa00d4d6c..f3a870d45 100644 --- a/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/DmsIcon.kt +++ b/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/DmsIcon.kt @@ -14,6 +14,7 @@ object DmsIcon { val Check = R.drawable.ic_check val Close = R.drawable.ic_close val Dinner = R.drawable.ic_dinner + val Up = R.drawable.ic_up val Down = R.drawable.ic_down val Forward = R.drawable.ic_forward val Home = R.drawable.ic_home diff --git a/core/design-system/src/main/res/drawable/ic_up.xml b/core/design-system/src/main/res/drawable/ic_up.xml new file mode 100644 index 000000000..ab1f1bb2d --- /dev/null +++ b/core/design-system/src/main/res/drawable/ic_up.xml @@ -0,0 +1,9 @@ + + + diff --git a/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdScreen.kt index febe48de9..30235d131 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdScreen.kt @@ -174,9 +174,14 @@ private fun UserInformationInputs( trailingIcon = { IconButton(onClick = { isDropdownMenuExpanded = !isDropdownMenuExpanded }) { Icon( - painter = if (isDropdownMenuExpanded) painterResource(id = com.google.android.material.R.drawable.material_ic_menu_arrow_up_black_24dp) - else painterResource(id = DmsIcon.Down), - contentDescription = "down_icon", + painter = painterResource( + if (isDropdownMenuExpanded) { + DmsIcon.Down + } else { + DmsIcon.Up + } + ), + contentDescription = "dropdown_menu_icon", ) } } From 382af080fb35470a1b03ae88080bcde24c58cabc Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 9 Apr 2024 08:25:17 +0900 Subject: [PATCH 100/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20student?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/outing/OutingViewModel.kt | 41 +------------------ 1 file changed, 1 insertion(+), 40 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt index 1745c7650..c8082e218 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt @@ -144,46 +144,7 @@ class OutingViewModel @Inject constructor( private fun fetchStudents() = viewModelScope.launch(Dispatchers.IO) { runCatching { - // FIXME - // studentRepository.fetchStudents() - listOf( - Student( - id = UUID.randomUUID(), - name = "박준수", - gradeClassNumber = "3211", - profileImageUrl = "www.naver.com", - ), - Student( - id = UUID.randomUUID(), - name = "준박수", - gradeClassNumber = "1234", - profileImageUrl = "www.naver.com", - ), - Student( - id = UUID.randomUUID(), - name = "박준혁", - gradeClassNumber = "2211", - profileImageUrl = "www.naver.com", - ), - Student( - id = UUID.randomUUID(), - name = "수준봐", - gradeClassNumber = "1111", - profileImageUrl = "www.naver.com", - ), - Student( - id = UUID.randomUUID(), - name = "코딱지", - gradeClassNumber = "4411", - profileImageUrl = "www.naver.com", - ), - Student( - id = UUID.randomUUID(), - name = "빅준자", - gradeClassNumber = "9213", - profileImageUrl = "www.naver.com", - ), - ) + studentRepository.fetchStudents() }.onSuccess { fetchedStudents -> println(fetchedStudents) reduce( From df2301da5365be029c8dc73f1b9d968b82186e19 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 9 Apr 2024 08:29:08 +0900 Subject: [PATCH 101/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20removal?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/outing/OutingApplicationScreen.kt | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt index b9285e892..183ddf3ca 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt @@ -15,6 +15,8 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.size import androidx.compose.foundation.lazy.items import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material.icons.Icons +import androidx.compose.material.icons.filled.Close import androidx.compose.material3.Card import androidx.compose.material3.CardDefaults import androidx.compose.material3.DropdownMenuItem @@ -29,8 +31,6 @@ import androidx.compose.material3.TimePicker import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.material3.rememberTimePickerState import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect -import androidx.compose.runtime.DisposableEffectResult import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -529,7 +529,7 @@ private fun StudentList( .horizontalPadding(), student = student, selected = selected, - onClick = onSelectStudent, + onClick = { onSelectStudent(student) }, ) } } @@ -541,7 +541,7 @@ private fun StudentCard( modifier: Modifier = Modifier, student: Student, selected: Boolean, - onClick: (Student) -> Unit, + onClick: () -> Unit, ) { Card( modifier = modifier.verticalPadding(PaddingDefaults.ExtraSmall), @@ -559,7 +559,7 @@ private fun StudentCard( null }, elevation = CardDefaults.cardElevation(defaultElevation = ShadowDefaults.SmallElevation), - onClick = { onClick(student) }, + onClick = onClick, ) { Row( modifier = Modifier.fillMaxWidth(), @@ -587,6 +587,14 @@ private fun StudentCard( student.name, ), ) + if (selected) { + IconButton(onClick = onClick) { + Icon( + imageVector = Icons.Default.Close, + contentDescription = stringResource(id = R.string.cancel), + ) + } + } } } } From b8fab29a4ca222e9188ba31f0f2d4f063f88d8da Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 9 Apr 2024 10:04:57 +0900 Subject: [PATCH 102/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20time?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/data/outing/model/OutingApplicationTime.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt b/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt index 40a9fce69..4fc58f4fe 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt @@ -14,7 +14,7 @@ data class OutingApplicationTime( ) fun OutingAvailableTimeResponse.toModel(): List = - this.availableTimes.map(OutingAvailableTimeResponse.AvailableTimeResponse::toModel) + this.availableTimes.toModel() fun List.toModel(): List = this.map(OutingAvailableTimeResponse.AvailableTimeResponse::toModel) From ed25f89684565f8d393f28e5c4056cb42ed8c295 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 9 Apr 2024 10:05:46 +0900 Subject: [PATCH 103/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20time=20respon?= =?UTF-8?q?se?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/network/outing/model/OutingAvailableTimeResponse.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt index 7ddfdeae9..adc23c3cf 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt @@ -8,7 +8,7 @@ import java.util.UUID data class OutingAvailableTimeResponse( @SerializedName("outing_available_time") val availableTimes: List, ) { - data class AvailableTimeResponse( + data class AvailableTimeResponse( @SerializedName("outing_available_time_id") val id: String, @SerializedName("outing_time") val startTime: LocalDateTime, @SerializedName("arrival_time") val endTime: LocalDateTime, From 9f05f155c06b9237045d0d9e10ae2c5ce351b0c4 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 9 Apr 2024 10:05:50 +0900 Subject: [PATCH 104/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20string=20reso?= =?UTF-8?q?urce?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/src/main/res/values/strings.xml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index 178eed307..c74091547 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -301,7 +301,7 @@ 동행자 작성한 정보가 파기됩니다. 계속하시겠습니까? 외출 신청 정보를 조회할 수 없습니다 - %02d:%02d + %s:%s 외출 유형이 존재하지 않습니다 선택 외출 유형 @@ -316,4 +316,5 @@ 학번/이름으로 검색해 보세요 선택한 학생 %s %s + 외출 유형이 선택되지 않았습니다. \ No newline at end of file From a6867606eb577a003be2be858ee2269b14665e78 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 9 Apr 2024 10:06:06 +0900 Subject: [PATCH 105/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20application?= =?UTF-8?q?=20req?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/network/outing/model/ApplyOutingRequest.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt index 6f24e2539..0e41a7250 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/ApplyOutingRequest.kt @@ -6,7 +6,7 @@ import org.threeten.bp.LocalDateTime import java.util.UUID data class ApplyOutingRequest( - @SerializedName("outing_date") val date: LocalDate, + @SerializedName("outing_date") val date: String, @SerializedName("outing_time") val startTime: String, @SerializedName("arrival_time") val endTime: String, @SerializedName("outing_type_title") val type: String, From 904d17eecadca1fa61503854e1a39ba741cda644 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 9 Apr 2024 10:06:16 +0900 Subject: [PATCH 106/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20applied=20app?= =?UTF-8?q?lication?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../outing/model/CurrentAppliedOutingApplication.kt | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt b/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt index f136c2345..1619171c5 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt @@ -3,19 +3,24 @@ package team.aliens.dms.android.data.outing.model import org.threeten.bp.LocalDate import org.threeten.bp.LocalDateTime import team.aliens.dms.android.network.outing.model.FetchCurrentAppliedOutingApplicationResponse +import team.aliens.dms.android.shared.date.toLocalDateTime data class CurrentAppliedOutingApplication( - val date: LocalDate, + val date: String, val type: String, val status: OutingStatus, - val startTime: LocalDateTime, - val endTime: LocalDateTime, + val startTime: String, + val endTime: String, val reason: String?, val companionNames: List, ) { // TODO enum class OutingStatus { - REQUESTED, OUTING, DONE, ; + REQUESTED, + OUTING, + DONE, + APPROVED, + ; } } From 2bb2547126aecdd4afb03ccd7db54f2ff9a80706 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 9 Apr 2024 10:06:20 +0900 Subject: [PATCH 107/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20dms=20app?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/team/aliens/dms/android/app/DmsApp.kt | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt b/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt index 73a65ba4a..20460b965 100644 --- a/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt +++ b/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt @@ -24,6 +24,7 @@ import team.aliens.dms.android.feature.outing.navigation.OutingNavGraph import team.aliens.dms.android.feature.signup.SignUpViewModel import team.aliens.dms.android.feature.signup.TermsUrl import team.aliens.dms.android.feature.signup.navigation.SignUpNavGraph +import java.util.UUID @Composable fun DmsApp( @@ -64,6 +65,11 @@ fun DmsApp( } hiltViewModel(parentEntry) } + dependency(OutingNavGraph) { + val parentEntry = remember(navBackStackEntry) { + navController.getBackStackEntry(OutingNavGraph.route) + } + } }, ) } From 798b67692c2a6766a9897850f467985297da4e86 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 9 Apr 2024 10:06:23 +0900 Subject: [PATCH 108/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20repo?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/outing/repository/OutingRepository.kt | 4 ++-- .../data/outing/repository/OutingRepositoryImpl.kt | 12 +++++++----- 2 files changed, 9 insertions(+), 7 deletions(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt index eb768f2df..4fb15db9a 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepository.kt @@ -13,8 +13,8 @@ abstract class OutingRepository { abstract suspend fun applyOuting( date: LocalDate, - startTime: String, - endTime: String, + startTime: LocalDateTime, + endTime: LocalDateTime, type: String, reason: String?, companionIds: List, diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt index b47cfc9da..025f55aa7 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/repository/OutingRepositoryImpl.kt @@ -3,12 +3,14 @@ package team.aliens.dms.android.data.outing.repository import org.threeten.bp.DayOfWeek import org.threeten.bp.LocalDate import org.threeten.bp.LocalDateTime +import org.threeten.bp.format.DateTimeFormatter import team.aliens.dms.android.data.outing.model.CurrentAppliedOutingApplication import team.aliens.dms.android.data.outing.model.OutingApplicationId import team.aliens.dms.android.data.outing.model.OutingApplicationTime import team.aliens.dms.android.data.outing.model.toModel import team.aliens.dms.android.network.outing.datasource.OutingNetworkDataSource import team.aliens.dms.android.network.outing.model.ApplyOutingRequest +import java.text.SimpleDateFormat import java.util.UUID import javax.inject.Inject @@ -20,16 +22,16 @@ class OutingRepositoryImpl @Inject constructor( override suspend fun applyOuting( date: LocalDate, - startTime: String, - endTime: String, + startTime: LocalDateTime, + endTime: LocalDateTime, type: String, reason: String?, companionIds: List ): OutingApplicationId = outingNetworkDataSource.applyOuting( req = ApplyOutingRequest( - date = date, - startTime = startTime, - endTime = endTime, + date = date.format(DateTimeFormatter.ISO_LOCAL_DATE), + startTime = startTime.format(DateTimeFormatter.ofPattern("hh:mm:00")), + endTime = endTime.format(DateTimeFormatter.ofPattern("hh:mm:00")), type = type, reason = reason, companionIds = companionIds, From e2729799a4ac96695653a1370bc7f5122b6ee51e Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 9 Apr 2024 10:06:30 +0900 Subject: [PATCH 109/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20scre?= =?UTF-8?q?ens?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/outing/OutingApplicationScreen.kt | 75 ++++++++++++++----- .../feature/outing/OutingStatusScreen.kt | 9 ++- 2 files changed, 65 insertions(+), 19 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt index 183ddf3ca..c61725173 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt @@ -31,6 +31,7 @@ import androidx.compose.material3.TimePicker import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.material3.rememberTimePickerState import androidx.compose.runtime.Composable +import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -41,20 +42,26 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.Brush import androidx.compose.ui.graphics.Color +import androidx.compose.ui.platform.LocalContext +import androidx.compose.ui.platform.LocalLifecycleOwner import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp +import androidx.lifecycle.Lifecycle +import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.compose.collectAsStateWithLifecycle import coil.compose.AsyncImage import com.ramcosta.composedestinations.annotation.Destination import kotlinx.coroutines.launch import org.threeten.bp.DayOfWeek +import org.threeten.bp.LocalDateTime import team.aliens.dms.android.core.designsystem.AlertDialog import team.aliens.dms.android.core.designsystem.Button import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar +import team.aliens.dms.android.core.designsystem.LocalToast import team.aliens.dms.android.core.designsystem.ModalBottomSheet import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.ShadowDefaults @@ -65,6 +72,7 @@ import team.aliens.dms.android.core.ui.DefaultHorizontalSpace import team.aliens.dms.android.core.ui.DefaultVerticalSpace import team.aliens.dms.android.core.ui.PaddingDefaults import team.aliens.dms.android.core.ui.bottomPadding +import team.aliens.dms.android.core.ui.collectInLaunchedEffectWithLifecycle import team.aliens.dms.android.core.ui.composable.FloatingNotice import team.aliens.dms.android.core.ui.endPadding import team.aliens.dms.android.core.ui.horizontalPadding @@ -74,6 +82,7 @@ import team.aliens.dms.android.core.ui.verticalPadding import team.aliens.dms.android.data.student.model.Student import team.aliens.dms.android.feature.R import team.aliens.dms.android.feature.outing.navigation.OutingNavigator +import java.util.UUID @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -87,6 +96,9 @@ fun OutingApplicationScreen( mutableStateOf(false) } val scope = rememberCoroutineScope() + val context = LocalContext.current + val toast = LocalToast.current + val lifeCycleOwner = LocalLifecycleOwner.current val startTimePickerState = rememberTimePickerState() val (shouldShowStartTimePicker, onChangeShouldShowStartTimePicker) = remember { @@ -97,7 +109,18 @@ fun OutingApplicationScreen( confirmButton = { TextButton( onClick = { - viewModel.postIntent(OutingIntent.UpdateOutingStartTime(value = "${startTimePickerState.hour}:${startTimePickerState.minute}")) + viewModel.postIntent( + OutingIntent.UpdateOutingStartTime( + value = LocalDateTime.of( + // TODO: 죄송합니다.. + 2006, + 5, + 8, + startTimePickerState.hour, + startTimePickerState.minute, + ), + ) + ) onChangeShouldShowStartTimePicker(false) }, ) { @@ -118,7 +141,18 @@ fun OutingApplicationScreen( confirmButton = { TextButton( onClick = { - viewModel.postIntent(OutingIntent.UpdateOutingEndTime(value = "${endTimePickerState.hour}:${endTimePickerState.minute}")) + viewModel.postIntent( + OutingIntent.UpdateOutingEndTime( + value = LocalDateTime.of( + // TODO: 죄송합니다.. + 2006, + 5, + 8, + endTimePickerState.hour, + endTimePickerState.minute, + ), + ) + ) onChangeShouldShowEndTimePicker(false) }, ) { @@ -166,8 +200,9 @@ fun OutingApplicationScreen( .fillMaxWidth() .heightIn(max = 240.dp), students = uiState.students?.filter { - it.name.contains(studentFilterValue) - || it.gradeClassNumber.contains(studentFilterValue) + it.name.contains(studentFilterValue) || it.gradeClassNumber.contains( + studentFilterValue + ) }, selectedStudents = uiState.selectedStudents, onSelectStudent = { student -> @@ -231,6 +266,17 @@ fun OutingApplicationScreen( } } } + viewModel.sideEffectFlow.collectInLaunchedEffectWithLifecycle { sideEffect -> + when (sideEffect) { + OutingSideEffect.OutingTypeNotSelected -> toast.showErrorToast( + message = context.getString(R.string.outing_application_error_outing_type_not_selected), + ) + + is OutingSideEffect.OutingApplicationSuccess -> navigator.navigateUp() + else -> {/* explicit blank */ + } + } + } Scaffold( topBar = { @@ -311,7 +357,7 @@ fun OutingApplicationScreen( indicator = { OutingInputDefaults.Indicator() }, ) { val time = remember(uiState.selectedOutingStartTime) { - uiState.selectedOutingStartTime.split(':').map(String::toInt) + uiState.selectedOutingStartTime } TextField( trailingIcon = { @@ -329,8 +375,8 @@ fun OutingApplicationScreen( }, value = stringResource( id = R.string.outing_format_duration_h_m, - time[0], - time[1], + time.hour, + time.minute, ), onValueChange = {}, readOnly = true, @@ -344,7 +390,7 @@ fun OutingApplicationScreen( indicator = { OutingInputDefaults.Indicator() }, ) { val time = remember(uiState.selectedOutingEndTime) { - uiState.selectedOutingEndTime.split(':').map(String::toInt) + uiState.selectedOutingEndTime } TextField( trailingIcon = { @@ -362,8 +408,8 @@ fun OutingApplicationScreen( }, value = stringResource( id = R.string.outing_format_duration_h_m, - time[0], - time[1], + time.hour, + time.minute, ), onValueChange = {}, readOnly = true, @@ -479,7 +525,7 @@ fun OutingApplicationScreen( .fillMaxWidth() .horizontalPadding() .bottomPadding(), - onClick = { /*TODO*/ }, + onClick = { viewModel.postIntent(OutingIntent.ApplyOuting) }, ) { Text(text = stringResource(id = R.string.outing_do_application)) } @@ -517,12 +563,7 @@ private fun StudentList( true } else { selectedStudents.any { it == student } - }/* - AnimatedVisibility( - visible = selected, - enter = fadeIn(), - exit = slideOutFromStart(), - ) {*/ + } StudentCard( modifier = Modifier .fillMaxWidth() diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt index 2874841c4..f2f89b977 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt @@ -16,6 +16,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.Text 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 @@ -95,6 +96,10 @@ fun OutingStatusScreen( } } + LaunchedEffect(uiState.applicationId != null) { + viewModel.postIntent(OutingIntent.FetchCurrentAppliedOutingApplication) + } + Scaffold( topBar = { DmsTopAppBar( @@ -162,7 +167,7 @@ fun OutingStatusScreen( private fun OutingInformationCard( modifier: Modifier = Modifier, title: String, - date: LocalDate, + date: String, time: String, companionNames: List, reason: String?, @@ -194,7 +199,7 @@ private fun OutingInformationCard( ) { // TODO Text( - text = date.toString(), + text = date, style = DmsTheme.typography.caption, color = DmsTheme.colorScheme.primary, ) From 0d93e9a19531967c71b33a513a6b87582ff83254 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 9 Apr 2024 10:06:33 +0900 Subject: [PATCH 110/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20response?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/FetchCurrentAppliedOutingApplicationResponse.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt index e5c629a76..8bd74951b 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt @@ -5,11 +5,11 @@ import org.threeten.bp.LocalDate import org.threeten.bp.LocalDateTime data class FetchCurrentAppliedOutingApplicationResponse( - @SerializedName("outing_date") val date: LocalDate, - @SerializedName("outing_type") val type: String, + @SerializedName("outing_date") val date: String, + @SerializedName("outing_type_title") val type: String, @SerializedName("status") val status: String, - @SerializedName("outing_time") val startTime: LocalDateTime, - @SerializedName("arrival_time") val endTime: LocalDateTime, + @SerializedName("outing_time") val startTime: String, + @SerializedName("arrival_time") val endTime: String, @SerializedName("reason") val reason: String?, @SerializedName("outing_companions") val companionNames: List, ) From 5554ba4ae49bfafe545b8477f22d07cee0443a4f Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 9 Apr 2024 10:06:37 +0900 Subject: [PATCH 111/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20vm?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/outing/OutingViewModel.kt | 48 +++++++++++-------- 1 file changed, 29 insertions(+), 19 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt index c8082e218..61d2022c2 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt @@ -45,6 +45,8 @@ class OutingViewModel @Inject constructor( student = intent.student, select = intent.select, ) + + OutingIntent.FetchCurrentAppliedOutingApplication -> fetchCurrentAppliedOutingApplication() } } @@ -73,6 +75,7 @@ class OutingViewModel @Inject constructor( ) }.onFailure { postSideEffect(OutingSideEffect.CurrentAppliedOutingApplicationNotFound) + it.printStackTrace() } } @@ -104,14 +107,14 @@ class OutingViewModel @Inject constructor( ), ) - private fun updateOutingStartTime(value: String) = reduce( + private fun updateOutingStartTime(value: LocalDateTime) = reduce( newState = stateFlow.value.copy( selectedOutingStartTime = value, ), ) - private fun updateOutingEndTime(value: String) = reduce( + private fun updateOutingEndTime(value: LocalDateTime) = reduce( newState = stateFlow.value.copy( selectedOutingEndTime = value, ), @@ -126,18 +129,21 @@ class OutingViewModel @Inject constructor( viewModelScope.launch(Dispatchers.IO) { runCatching { - /*outingRepository.applyOuting( + outingRepository.applyOuting( date = capturedState.capturedNow.toLocalDate(), - startTime = capturedState.selectedOutingStartTime + ":00", - endTime = capturedState.selectedOutingEndTime + ":00", + startTime = capturedState.selectedOutingStartTime, + endTime = capturedState.selectedOutingEndTime, type = capturedState.selectedOutingType, - reason = if (capturedState.reason.isBlank()) { - null - } else { - capturedState.reason - }, - companionIds = - )*/ + reason = capturedState.reason.ifBlank { null }, + companionIds = capturedState.selectedStudents.map { it.id }, + ) + }.onSuccess { applicationId -> + reduce( + newState = capturedState.copy( + applicationId = applicationId, + ), + ) + postSideEffect(OutingSideEffect.OutingApplicationSuccess(applicationId)) } } } @@ -146,7 +152,6 @@ class OutingViewModel @Inject constructor( runCatching { studentRepository.fetchStudents() }.onSuccess { fetchedStudents -> - println(fetchedStudents) reduce( newState = stateFlow.value.copy( students = fetchedStudents, @@ -183,11 +188,12 @@ data class OutingUiState( val selectedOutingType: String?, val reason: String, val capturedNow: LocalDateTime, - val selectedOutingStartTime: String, - val selectedOutingEndTime: String, + val selectedOutingStartTime: LocalDateTime, + val selectedOutingEndTime: LocalDateTime, val companionIds: List, val students: List?, val selectedStudents: List, + val applicationId: UUID?, ) : UiState() { companion object { fun initial(): OutingUiState { @@ -200,11 +206,12 @@ data class OutingUiState( reason = "", capturedNow = capturedNow, // TODO: remove hard-coded string resources from viewmodel - selectedOutingEndTime = "${capturedNow.hour}:${capturedNow.minute}", - selectedOutingStartTime = "${capturedNow.hour}:${capturedNow.minute}", + selectedOutingEndTime = now, + selectedOutingStartTime = now, companionIds = emptyList(), students = null, selectedStudents = emptyList(), + applicationId = null, ) } } @@ -214,16 +221,19 @@ sealed class OutingIntent : Intent() { data object CancelCurrentApplication : OutingIntent() class UpdateSelectedOutingType(val value: String) : OutingIntent() class UpdateReason(val value: String) : OutingIntent() - class UpdateOutingStartTime(val value: String) : OutingIntent() - class UpdateOutingEndTime(val value: String) : OutingIntent() + class UpdateOutingStartTime(val value: LocalDateTime) : OutingIntent() + class UpdateOutingEndTime(val value: LocalDateTime) : OutingIntent() data object ApplyOuting : OutingIntent() class SelectStudent( val student: Student, val select: Boolean, ) : OutingIntent() + + data object FetchCurrentAppliedOutingApplication : OutingIntent() } sealed class OutingSideEffect : SideEffect() { data object CurrentAppliedOutingApplicationNotFound : OutingSideEffect() data object OutingTypeNotSelected : OutingSideEffect() + class OutingApplicationSuccess(val applicationId: UUID) : OutingSideEffect() } From 3a3cef211337b86ea36384fb29c62831cad6e864 Mon Sep 17 00:00:00 2001 From: uiel Date: Tue, 9 Apr 2024 14:51:52 +0900 Subject: [PATCH 112/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20navigator?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/aliens/dms/android/app/navigation/DmsNavigator.kt | 5 +++-- .../dms/android/feature/main/navigation/MainNavigator.kt | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt b/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt index 64029a1bd..0c43f4d1d 100644 --- a/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt +++ b/app/src/main/java/team/aliens/dms/android/app/navigation/DmsNavigator.kt @@ -13,6 +13,7 @@ import team.aliens.dms.android.app.navigation.authorized.AuthorizedNavGraph import team.aliens.dms.android.app.navigation.authorized.AuthorizedNavigator import team.aliens.dms.android.app.navigation.unauthorized.UnauthorizedNavGraph import team.aliens.dms.android.app.navigation.unauthorized.UnauthorizedNavigator +import team.aliens.dms.android.data.point.model.PointType import team.aliens.dms.android.feature.destinations.EditPasswordSetPasswordScreenDestination import team.aliens.dms.android.feature.destinations.EditProfileImageScreenDestination import team.aliens.dms.android.feature.destinations.EnterEmailScreenDestination @@ -69,8 +70,8 @@ class DmsNavigator( navController.navigateSingleTop(EditProfileImageScreenDestination() within AuthorizedNavGraph) } - override fun openPointHistory() { - navController.navigateSingleTop(PointHistoryScreenDestination within navGraph) + override fun openPointHistory(pointType: PointType) { + navController.navigateSingleTop(PointHistoryScreenDestination(pointType) within navGraph) } override fun openEditPasswordNav() { diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/navigation/MainNavigator.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/navigation/MainNavigator.kt index f81797e5c..dce65e79e 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/navigation/MainNavigator.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/navigation/MainNavigator.kt @@ -1,5 +1,6 @@ package team.aliens.dms.android.feature.main.navigation +import team.aliens.dms.android.data.point.model.PointType import java.util.UUID interface MainNavigator { @@ -14,7 +15,7 @@ interface MainNavigator { fun openEditProfileImage() - fun openPointHistory() + fun openPointHistory(pointType: PointType) fun openEditPasswordNav() From abd0c01173f69772159433cda9ec307381bea01a Mon Sep 17 00:00:00 2001 From: uiel Date: Tue, 9 Apr 2024 14:53:21 +0900 Subject: [PATCH 113/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20PointType=20?= =?UTF-8?q?=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../feature/main/mypage/MyPageScreen.kt | 19 ++++++++++++++----- .../feature/point/PointHistoryScreen.kt | 6 ++++++ .../feature/point/PointHistoryViewModel.kt | 10 +++------- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt index 6f462c654..6fe3609b2 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt @@ -54,6 +54,7 @@ import team.aliens.dms.android.core.ui.horizontalPadding import team.aliens.dms.android.core.ui.startPadding import team.aliens.dms.android.core.ui.topPadding import team.aliens.dms.android.core.ui.verticalPadding +import team.aliens.dms.android.data.point.model.PointType import team.aliens.dms.android.feature.R import team.aliens.dms.android.shared.model.Sex @@ -63,7 +64,7 @@ import team.aliens.dms.android.shared.model.Sex internal fun MyPageScreen( modifier: Modifier = Modifier, onNavigateToEditProfileImage: () -> Unit, - onNavigateToPointHistory: () -> Unit, + onNavigateToPointHistory: (PointType) -> Unit, onNavigateToEditPassword: () -> Unit, onNavigateToUnauthorizedNav: () -> Unit, ) { @@ -162,6 +163,7 @@ internal fun MyPageScreen( modifier = Modifier.fillMaxWidth(), bonusPoint = uiState.myPage?.bonusPoint, minusPoint = uiState.myPage?.minusPoint, + onNavigateToPointHistory = onNavigateToPointHistory, ) Options( modifier = Modifier.fillMaxWidth(), @@ -305,6 +307,7 @@ private fun PhraseCard( @Composable private fun PointCards( modifier: Modifier = Modifier, + onNavigateToPointHistory: (PointType) -> Unit, bonusPoint: Int?, minusPoint: Int?, ) { @@ -315,7 +318,10 @@ private fun PointCards( PointCard( modifier = Modifier .weight(1f) - .startPadding(), + .startPadding() + .clickable( + onClick = { onNavigateToPointHistory(PointType.BONUS) } + ), type = PointCardType.BONUS, // TODO: fix point = bonusPoint ?: 0, @@ -323,7 +329,10 @@ private fun PointCards( PointCard( modifier = Modifier .weight(1f) - .endPadding(), + .endPadding() + .clickable( + onClick = { onNavigateToPointHistory(PointType.MINUS) } + ), type = PointCardType.MINUS, // TODO: fix point = minusPoint ?: 0, @@ -408,7 +417,7 @@ private enum class PointCardType { @Composable private fun Options( modifier: Modifier = Modifier, - onNavigateToPointHistory: () -> Unit, + onNavigateToPointHistory: (PointType) -> Unit, onNavigateToEditPassword: () -> Unit, onSignOutClick: () -> Unit, onWithdrawalClick: () -> Unit, @@ -418,7 +427,7 @@ private fun Options( listOf( Option( titleRes = R.string.my_page_check_point_history, - onClick = onNavigateToPointHistory, + onClick = { onNavigateToPointHistory(PointType.ALL) }, ), Option( titleRes = R.string.my_page_edit_password, diff --git a/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt index 4cb934aae..fd2bb65ff 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt @@ -14,6 +14,7 @@ import androidx.compose.material3.Icon import androidx.compose.material3.IconButton import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.ui.Modifier import androidx.compose.ui.res.painterResource @@ -48,10 +49,15 @@ import team.aliens.dms.android.feature.point.navigation.PointHistoryNavigator internal fun PointHistoryScreen( modifier: Modifier = Modifier, navigator: PointHistoryNavigator, + pointType: PointType, ) { val viewModel: PointHistoryViewModel = hiltViewModel() val uiState by viewModel.stateFlow.collectAsStateWithLifecycle() + LaunchedEffect(Unit) { + viewModel.fetchPoints(pointType) + } + DmsScaffold( modifier = modifier, topBar = { diff --git a/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryViewModel.kt index 558a05f6f..60d45c898 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryViewModel.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryViewModel.kt @@ -29,20 +29,16 @@ internal class PointHistoryViewModel @Inject constructor( private lateinit var minusPoints: List private var scoreOfMinusPoints by Delegates.notNull() - init { - fetchPoints() - } - override fun processIntent(intent: PointHistoryIntent) { when (intent) { is PointHistoryIntent.UpdateSelectedPointType -> updatePoints(pointType = intent.pointType) } } - private fun fetchPoints() { + internal fun fetchPoints(pointType: PointType) { viewModelScope.launch(Dispatchers.IO) { runCatching { - pointRepository.fetchPoints(type = PointType.ALL) + pointRepository.fetchPoints(type = pointType) }.onSuccess { pointStatus -> this@PointHistoryViewModel.allPoints = pointStatus.points this@PointHistoryViewModel.scoreOfAllPoints = pointStatus.totalPoints @@ -55,7 +51,7 @@ internal class PointHistoryViewModel @Inject constructor( this@PointHistoryViewModel.minusPoints = minusPoints this@PointHistoryViewModel.scoreOfMinusPoints = minusPoints.sumOf { it.score } - updatePoints(PointType.ALL) + updatePoints(pointType) } } } From fe527494a0cf4d380e16a097d02aa3eb91943222 Mon Sep 17 00:00:00 2001 From: uielPark Date: Thu, 11 Apr 2024 19:16:43 +0900 Subject: [PATCH 114/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20string?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- feature/src/main/res/values/strings.xml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index 4cee5f428..1e9c41782 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -181,8 +181,10 @@ %s 으로 아이디가 전송되었습니다 학교를 선택해주세요 - 위 정보로 가입된 계정이 없습니다 + 메뉴 보기 + 위 정보로 가입된 계정이 없습니다 + 학교 정보를 가져올 수 없습니다 오늘의 급식 급식이 없습니다 From 05097ad74f7c4fc9cf5eed65387e336e160a0ea2 Mon Sep 17 00:00:00 2001 From: uielPark Date: Thu, 11 Apr 2024 19:17:54 +0900 Subject: [PATCH 115/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20SideEffect=20?= =?UTF-8?q?=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EC=88=98=EC=A0=95=20=EB=B0=8F=20?= =?UTF-8?q?UiState=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/feature/findid/FindIdScreen.kt | 27 +++--- .../android/feature/findid/FindIdViewModel.kt | 82 ++++++++++--------- 2 files changed, 57 insertions(+), 52 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdScreen.kt index 30235d131..7233aefbb 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdScreen.kt @@ -74,7 +74,7 @@ internal fun FindIdScreen( Text( text = String.format( stringResource(id = R.string.find_id_send_id_to_email), - uiState.email + uiState.email, ) ) }, @@ -92,11 +92,13 @@ internal fun FindIdScreen( viewModel.sideEffectFlow.collectInLaunchedEffectWithLifecycle { sideEffect -> when (sideEffect) { - FindIdSideEffect.Success -> { + FindIdSideEffect.UserFound -> { isDialogShow = true } - FindIdSideEffect.NotFound -> toast.showErrorToast(context.getString(R.string.error_not_found)) + FindIdSideEffect.UserNotFound -> toast.showErrorToast(context.getString(R.string.error_not_found)) + FindIdSideEffect.SchoolNotFound -> toast.showErrorToast(context.getString(R.string.find_id_error_school_not_found)) + FindIdSideEffect.SchoolNotSelected -> toast.showErrorToast(context.getString(R.string.find_id_select_school)) } } @@ -108,7 +110,7 @@ internal fun FindIdScreen( navigationIcon = { IconButton(onClick = navigator::navigateUp) { Icon( - painter = painterResource(id = R.drawable.ic_baseline_arrow_back_24), + painter = painterResource(id = DmsIcon.Back), contentDescription = stringResource(id = R.string.top_bar_back_button), ) } @@ -121,7 +123,7 @@ internal fun FindIdScreen( .fillMaxSize() .padding(paddingValues) .horizontalPadding() - .imePadding() + .imePadding(), ) { Banner( modifier = Modifier @@ -141,7 +143,7 @@ internal fun FindIdScreen( modifier = Modifier .fillMaxWidth() .bottomPadding(), - onClick = viewModel::onButtonClick, + onClick = { viewModel.postIntent(FindIdIntent.FindId) }, enabled = uiState.buttonEnabled, ) { Text(text = stringResource(id = R.string.find_id)) @@ -167,7 +169,7 @@ private fun UserInformationInputs( modifier = Modifier.clickable( onClick = { isDropdownMenuExpanded = !isDropdownMenuExpanded } ), - value = state.schoolName, + value = state.selectedSchool?.name ?: "", onValueChange = { }, readOnly = true, hint = { Text(text = stringResource(id = R.string.find_id_select_school)) }, @@ -181,7 +183,7 @@ private fun UserInformationInputs( DmsIcon.Up } ), - contentDescription = "dropdown_menu_icon", + contentDescription = stringResource(id = R.string.find_id_show_menu), ) } } @@ -192,15 +194,12 @@ private fun UserInformationInputs( expanded = isDropdownMenuExpanded, onDismissRequest = { isDropdownMenuExpanded = false }, ) { - state.schoolList.forEach { item -> + state.schoolList?.forEach { school -> DropdownMenuItem( - text = { Text(text = item.name) }, + text = { Text(text = school.name) }, onClick = { viewModel.postIntent( - FindIdIntent.UpdateSchoolId( - schoolId = item.id, - schoolName = item.name, - ) + FindIdIntent.UpdateSchoolId(value = school) ) isDropdownMenuExpanded = false }, diff --git a/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdViewModel.kt index 41f3e6942..7040cfd9f 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdViewModel.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdViewModel.kt @@ -12,7 +12,6 @@ import team.aliens.dms.android.core.ui.mvi.UiState import team.aliens.dms.android.data.school.model.School import team.aliens.dms.android.data.school.repository.SchoolRepository import team.aliens.dms.android.data.student.repository.StudentRepository -import java.util.UUID import javax.inject.Inject @HiltViewModel @@ -30,19 +29,20 @@ internal class FindIdViewModel @Inject constructor( override fun processIntent(intent: FindIdIntent) { when (intent) { is FindIdIntent.UpdateSchoolId -> this.updateSchoolId( - schoolId = intent.schoolId, - schoolName = intent.schoolName + selectedSchool = intent.value ) is FindIdIntent.UpdateName -> this.updateName(name = intent.value) is FindIdIntent.UpdateGrade -> this.updateGrade(grade = intent.value) is FindIdIntent.UpdateClass -> this.updateClassRoom(classRoom = intent.value) is FindIdIntent.UpdateNumber -> this.updateNumber(number = intent.value) + + is FindIdIntent.FindId -> onButtonClick() } } - - private fun updateSchoolId(schoolId: UUID, schoolName: String): Boolean = reduce( - newState = stateFlow.value.copy(schoolId = schoolId, schoolName = schoolName) + + private fun updateSchoolId(selectedSchool: School): Boolean = reduce( + newState = stateFlow.value.copy(selectedSchool = selectedSchool) ).also { updateButtonEnable(checkInAvailable()) } private fun updateName(name: String): Boolean = reduce( @@ -65,32 +65,37 @@ internal class FindIdViewModel @Inject constructor( reduce(newState = stateFlow.value.copy(buttonEnabled = buttonEnabled)) private fun checkInAvailable(): Boolean { - val uiState = stateFlow.value + val capturedState = stateFlow.value - val nameEntered = uiState.name.isNotBlank() - val gradeEntered = uiState.grade.isNotBlank() - val classRoomEntered = uiState.classRoom.isNotBlank() - val numberEntered = uiState.number.isNotBlank() + val nameEntered = capturedState.name.isNotBlank() + val gradeEntered = capturedState.grade.isNotBlank() + val classRoomEntered = capturedState.classRoom.isNotBlank() + val numberEntered = capturedState.number.isNotBlank() return nameEntered && gradeEntered && classRoomEntered && numberEntered } - internal fun onButtonClick() { + private fun onButtonClick() = run { with(stateFlow.value) { - viewModelScope.launch(Dispatchers.IO) { - runCatching { - studentRepository.findId( - schoolId = schoolId, - studentName = name, - grade = grade.toInt(), - classRoom = classRoom.toInt(), - number = number.toInt(), - ) - }.onSuccess { email -> - reduce(newState = stateFlow.value.copy(email = email)) - postSideEffect(FindIdSideEffect.Success) - }.onFailure { - postSideEffect(FindIdSideEffect.NotFound) + if (selectedSchool == null) { + postSideEffect(FindIdSideEffect.SchoolNotSelected) + return@run + } else { + viewModelScope.launch(Dispatchers.IO) { + runCatching { + studentRepository.findId( + schoolId = selectedSchool.id, + studentName = selectedSchool.name, + grade = grade.toInt(), + classRoom = classRoom.toInt(), + number = number.toInt(), + ) + }.onSuccess { email -> + reduce(newState = stateFlow.value.copy(email = email)) + postSideEffect(FindIdSideEffect.UserFound) + }.onFailure { + postSideEffect(FindIdSideEffect.UserNotFound) + } } } } @@ -100,10 +105,10 @@ internal class FindIdViewModel @Inject constructor( viewModelScope.launch(Dispatchers.IO) { runCatching { schoolRepository.fetchSchools() - }.onSuccess { - reduce(newState = stateFlow.value.copy(schoolList = it)) + }.onSuccess { fetchSchools -> + reduce(newState = stateFlow.value.copy(schoolList = fetchSchools)) }.onFailure { - postSideEffect(FindIdSideEffect.NotFound) + postSideEffect(FindIdSideEffect.SchoolNotFound) } } } @@ -111,10 +116,9 @@ internal class FindIdViewModel @Inject constructor( internal data class FindIdUiState( - val schoolList: List, + val schoolList: List?, val email: String, - val schoolId: UUID, - val schoolName: String, + val selectedSchool: School?, val name: String, val grade: String, val classRoom: String, @@ -123,10 +127,9 @@ internal data class FindIdUiState( ) : UiState() { companion object { fun initial() = FindIdUiState( - schoolList = emptyList(), + schoolList = null, email = "", - schoolId = UUID.randomUUID(), - schoolName = "", + selectedSchool = null, name = "", grade = "", classRoom = "", @@ -137,14 +140,17 @@ internal data class FindIdUiState( } internal sealed class FindIdIntent : Intent() { - class UpdateSchoolId(val schoolId: UUID, val schoolName: String) : FindIdIntent() + class UpdateSchoolId(val value: School) : FindIdIntent() class UpdateName(val value: String) : FindIdIntent() class UpdateGrade(val value: String) : FindIdIntent() class UpdateClass(val value: String) : FindIdIntent() class UpdateNumber(val value: String) : FindIdIntent() + data object FindId : FindIdIntent() } internal sealed class FindIdSideEffect : SideEffect() { - data object Success : FindIdSideEffect() - data object NotFound : FindIdSideEffect() + data object UserFound : FindIdSideEffect() + data object UserNotFound : FindIdSideEffect() + data object SchoolNotFound : FindIdSideEffect() + data object SchoolNotSelected : FindIdSideEffect() } From 5b98b1883438961cec719827eab2de19f535701f Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 14 Apr 2024 13:19:10 +0900 Subject: [PATCH 116/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20time=20format?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/feature/outing/OutingApplicationScreen.kt | 4 ++-- feature/src/main/res/values/strings.xml | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt index c61725173..c4708d1d0 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt @@ -374,7 +374,7 @@ fun OutingApplicationScreen( } }, value = stringResource( - id = R.string.outing_format_duration_h_m, + id = R.string.outing_format_time_h_m, time.hour, time.minute, ), @@ -407,7 +407,7 @@ fun OutingApplicationScreen( } }, value = stringResource( - id = R.string.outing_format_duration_h_m, + id = R.string.outing_format_time_h_m, time.hour, time.minute, ), diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index c74091547..19e134a82 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -301,7 +301,8 @@ 동행자 작성한 정보가 파기됩니다. 계속하시겠습니까? 외출 신청 정보를 조회할 수 없습니다 - %s:%s + %s ~ %s + %02d:%02d 외출 유형이 존재하지 않습니다 선택 외출 유형 From 4cb3a581eedf4e682f3b21316ea6eb1c793c14dd Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 14 Apr 2024 13:35:50 +0900 Subject: [PATCH 117/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20canc?= =?UTF-8?q?el?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../model/CurrentAppliedOutingApplication.kt | 6 ++-- .../feature/outing/OutingStatusScreen.kt | 32 +++++++++---------- .../android/feature/outing/OutingViewModel.kt | 13 +++++++- ...CurrentAppliedOutingApplicationResponse.kt | 3 +- 4 files changed, 32 insertions(+), 22 deletions(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt b/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt index 1619171c5..e0ccd2e2f 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/model/CurrentAppliedOutingApplication.kt @@ -1,11 +1,10 @@ package team.aliens.dms.android.data.outing.model -import org.threeten.bp.LocalDate -import org.threeten.bp.LocalDateTime import team.aliens.dms.android.network.outing.model.FetchCurrentAppliedOutingApplicationResponse -import team.aliens.dms.android.shared.date.toLocalDateTime +import java.util.UUID data class CurrentAppliedOutingApplication( + val id: UUID, val date: String, val type: String, val status: OutingStatus, @@ -26,6 +25,7 @@ data class CurrentAppliedOutingApplication( fun FetchCurrentAppliedOutingApplicationResponse.toModel(): CurrentAppliedOutingApplication = CurrentAppliedOutingApplication( + id = UUID.fromString(this.id), date = this.date, type = this.type, status = CurrentAppliedOutingApplication.OutingStatus.valueOf(this.status), diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt index f2f89b977..e095675a6 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt @@ -4,8 +4,10 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.Row +import androidx.compose.foundation.layout.Spacer 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.lazy.LazyRow import androidx.compose.foundation.lazy.itemsIndexed @@ -26,9 +28,9 @@ import androidx.compose.ui.platform.LocalContext import androidx.compose.ui.res.painterResource import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight +import androidx.compose.ui.text.style.TextAlign import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination -import org.threeten.bp.LocalDate import team.aliens.dms.android.core.designsystem.AlertDialog import team.aliens.dms.android.core.designsystem.Button import team.aliens.dms.android.core.designsystem.ButtonDefaults @@ -42,7 +44,6 @@ import team.aliens.dms.android.core.ui.DefaultHorizontalSpace import team.aliens.dms.android.core.ui.DefaultVerticalSpace import team.aliens.dms.android.core.ui.PaddingDefaults import team.aliens.dms.android.core.ui.bottomPadding -import team.aliens.dms.android.core.ui.collectInLaunchedEffectWithLifecycle import team.aliens.dms.android.core.ui.horizontalPadding import team.aliens.dms.android.core.ui.startPadding import team.aliens.dms.android.core.ui.topPadding @@ -70,7 +71,10 @@ fun OutingStatusScreen( onDismissRequest = { onChangeShouldShowCancelOutingDialog(false) }, confirmButton = { TextButton( - onClick = { viewModel.postIntent(OutingIntent.CancelCurrentApplication) }, + onClick = { + viewModel.postIntent(OutingIntent.CancelCurrentApplication) + onChangeShouldShowCancelOutingDialog(false) + }, ) { Text(text = stringResource(id = R.string.accept)) } @@ -85,17 +89,6 @@ fun OutingStatusScreen( ) } - viewModel.sideEffectFlow.collectInLaunchedEffectWithLifecycle { sideEffect -> - when (sideEffect) { - OutingSideEffect.CurrentAppliedOutingApplicationNotFound -> toast.showErrorToast( - message = context.getString(R.string.outing_failed_to_fetch_current_applied_outing_application), - ) - - else -> {/* explicit blank */ - } - } - } - LaunchedEffect(uiState.applicationId != null) { viewModel.postIntent(OutingIntent.FetchCurrentAppliedOutingApplication) } @@ -146,7 +139,13 @@ fun OutingStatusScreen( reason = outingApplication.reason, onCancelApplication = { onChangeShouldShowCancelOutingDialog(true) }, ) - } + } ?: Text( + modifier = Modifier + .fillMaxWidth() + .topPadding(), + textAlign = TextAlign.Center, + text = stringResource(id = R.string.outing_failed_to_fetch_current_applied_outing_application) + ) } if (uiState.currentAppliedOutingApplication == null) { Button( @@ -197,7 +196,6 @@ private fun OutingInformationCard( horizontalArrangement = Arrangement.SpaceBetween, verticalAlignment = Alignment.CenterVertically, ) { - // TODO Text( text = date, style = DmsTheme.typography.caption, @@ -264,6 +262,8 @@ private fun OutingInformationCard( text = reason, ) } + } else { + Spacer(modifier = Modifier.height(DefaultVerticalSpace)) } } } diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt index 61d2022c2..93eb98efd 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt @@ -80,7 +80,18 @@ class OutingViewModel @Inject constructor( } private fun cancelApplication() = viewModelScope.launch(Dispatchers.IO) { - + val capturedState = stateFlow.value + runCatching { + outingRepository.cancelOuting( + applicationId = capturedState.currentAppliedOutingApplication!!.id, + ) + }.onSuccess { + reduce( + newState = capturedState.copy( + currentAppliedOutingApplication = null, + ), + ) + } } private fun fetchOutingTypes() = viewModelScope.launch(Dispatchers.IO) { diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt index 8bd74951b..af845242d 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/FetchCurrentAppliedOutingApplicationResponse.kt @@ -1,10 +1,9 @@ package team.aliens.dms.android.network.outing.model import com.google.gson.annotations.SerializedName -import org.threeten.bp.LocalDate -import org.threeten.bp.LocalDateTime data class FetchCurrentAppliedOutingApplicationResponse( + @SerializedName("id") val id: String, @SerializedName("outing_date") val date: String, @SerializedName("outing_type_title") val type: String, @SerializedName("status") val status: String, From faa550a783eb414d88757e3a8676b8eddd6b4ff1 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 14 Apr 2024 13:42:39 +0900 Subject: [PATCH 118/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20find=20id?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../team/aliens/dms/android/feature/findid/FindIdScreen.kt | 4 ++-- feature/src/main/res/values/strings.xml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdScreen.kt index 7233aefbb..3ae500ae4 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/findid/FindIdScreen.kt @@ -39,9 +39,9 @@ import team.aliens.dms.android.core.designsystem.AlertDialog import team.aliens.dms.android.core.designsystem.Button import team.aliens.dms.android.core.designsystem.ContainedButton import team.aliens.dms.android.core.designsystem.DmsIcon -import team.aliens.dms.android.core.designsystem.DmsScaffold import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.LocalToast +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.TextField import team.aliens.dms.android.core.designsystem.clickable import team.aliens.dms.android.core.ui.Banner @@ -102,7 +102,7 @@ internal fun FindIdScreen( } } - DmsScaffold( + Scaffold( modifier = Modifier.fillMaxSize(), topBar = { DmsTopAppBar( diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index caa60e007..9283d819b 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -172,7 +172,7 @@ 로그인 화면으로 - + 이름 학년 From c436c93da1dd570103f1a38e40ff83dbc2f175ce Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 14 Apr 2024 13:43:42 +0900 Subject: [PATCH 119/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20point=20histo?= =?UTF-8?q?ry?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aliens/dms/android/feature/point/PointHistoryScreen.kt | 4 ++-- feature/src/main/res/values/strings.xml | 4 ++++ 2 files changed, 6 insertions(+), 2 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt index 67838bfe7..379861b04 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt @@ -24,10 +24,10 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.ButtonDefaults import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.OutlinedButton +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.ShadowDefaults import team.aliens.dms.android.core.designsystem.VerticallyFadedLazyColumn import team.aliens.dms.android.core.ui.DefaultHorizontalSpace @@ -58,7 +58,7 @@ internal fun PointHistoryScreen( viewModel.fetchPoints(pointType) } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index 9283d819b..cf7d2b9b8 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -10,6 +10,7 @@ 아이디 비밀번호 인증 + 새로고침 확인 닫기 @@ -327,4 +328,7 @@ 선택한 학생 %s %s 외출 유형이 선택되지 않았습니다. + + + 새로 고침 성공 \ No newline at end of file From 76183ca3ea97bb66213a0b839ee246397286e622 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 14 Apr 2024 13:44:52 +0900 Subject: [PATCH 120/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20reset=20passw?= =?UTF-8?q?ord?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../resetpassword/1_AccountVerificationScreen.kt | 4 ++-- .../2_ResetPasswordEnterEmailVerificationCodeScreen.kt | 4 ++-- .../feature/resetpassword/3_SetPasswordScreen.kt | 4 ++-- feature/src/main/res/values/strings.xml | 10 ++++++++++ 4 files changed, 16 insertions(+), 6 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/1_AccountVerificationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/1_AccountVerificationScreen.kt index 17b83340d..e7eb6a14b 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/1_AccountVerificationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/1_AccountVerificationScreen.kt @@ -29,10 +29,10 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import kotlinx.coroutines.delay import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.DmsScaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.LocalToast +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.ShadowDefaults import team.aliens.dms.android.core.designsystem.TextField import team.aliens.dms.android.core.ui.Banner @@ -87,7 +87,7 @@ fun AccountVerificationScreen( } } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/2_ResetPasswordEnterEmailVerificationCodeScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/2_ResetPasswordEnterEmailVerificationCodeScreen.kt index 2c5807f4c..5f69a5546 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/2_ResetPasswordEnterEmailVerificationCodeScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/2_ResetPasswordEnterEmailVerificationCodeScreen.kt @@ -27,10 +27,10 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.ButtonDefaults import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.DmsScaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.LocalToast +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.TextButton import team.aliens.dms.android.core.designsystem.VerificationCodeInput import team.aliens.dms.android.core.designsystem.VerificationCodeInputDefaults @@ -116,7 +116,7 @@ internal fun ResetPasswordEnterEmailVerificationCodeScreen( } } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/3_SetPasswordScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/3_SetPasswordScreen.kt index 4786eee56..23ff00f8b 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/3_SetPasswordScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/resetpassword/3_SetPasswordScreen.kt @@ -24,9 +24,9 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.AlertDialog import team.aliens.dms.android.core.designsystem.ContainedButton -import team.aliens.dms.android.core.designsystem.DmsScaffold import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.LocalToast +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.TextButton import team.aliens.dms.android.core.ui.Banner import team.aliens.dms.android.core.ui.BannerDefaults @@ -95,7 +95,7 @@ fun ResetPasswordSetPasswordScreen( } } - DmsScaffold( + Scaffold( modifier = modifier, topBar = { DmsTopAppBar( diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index cf7d2b9b8..aa4beedad 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -329,6 +329,16 @@ %s %s 외출 유형이 선택되지 않았습니다. + + 일치하는 아이디가 존재하지 않습니다. + 아이디 입력 + 본인확인 인증 + 아이디와 일치하는 이메일입니다 + 아이디 형식이 일치하지 않습니다. + 이름 입력 + 이메일 입력 + 비밀번호가 변경되었습니다. + 로그인 화면으로 새로 고침 성공 \ No newline at end of file From 55de376548732e779f8cddc607fb694524837e59 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 14 Apr 2024 13:46:34 +0900 Subject: [PATCH 121/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20terms?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/src/main/java/team/aliens/dms/android/app/DmsApp.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt b/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt index 3f0cd6fb2..fa32d9760 100644 --- a/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt +++ b/app/src/main/java/team/aliens/dms/android/app/DmsApp.kt @@ -24,7 +24,7 @@ import team.aliens.dms.android.feature.outing.navigation.OutingNavGraph import team.aliens.dms.android.feature.signup.SignUpViewModel import team.aliens.dms.android.feature.signup.TermsUrl import team.aliens.dms.android.feature.signup.navigation.SignUpNavGraph -import java.util.UUID +import team.aliens.dms.android.network.BuildConfig @Composable fun DmsApp( From 33d39edbcebd0537152da7223e9a56ec951a2a29 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 14 Apr 2024 13:56:03 +0900 Subject: [PATCH 122/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20time?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../data/outing/model/OutingApplicationTime.kt | 5 ++--- .../android/feature/outing/OutingApplicationScreen.kt | 11 +++-------- feature/src/main/res/values/strings.xml | 2 +- .../outing/model/OutingAvailableTimeResponse.kt | 11 ++++------- 4 files changed, 10 insertions(+), 19 deletions(-) diff --git a/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt b/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt index 4fc58f4fe..f30811a53 100644 --- a/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt +++ b/data/src/main/java/team/aliens/dms/android/data/outing/model/OutingApplicationTime.kt @@ -1,14 +1,13 @@ package team.aliens.dms.android.data.outing.model import org.threeten.bp.DayOfWeek -import org.threeten.bp.LocalDateTime import team.aliens.dms.android.network.outing.model.OutingAvailableTimeResponse import java.util.UUID data class OutingApplicationTime( val id: UUID, - val startTime: LocalDateTime, - val endTime: LocalDateTime, + val startTime: String, + val endTime: String, val available: Boolean, val dayOfWeek: DayOfWeek, ) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt index c4708d1d0..79d43ab4f 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt @@ -31,7 +31,6 @@ import androidx.compose.material3.TimePicker import androidx.compose.material3.rememberModalBottomSheetState import androidx.compose.material3.rememberTimePickerState import androidx.compose.runtime.Composable -import androidx.compose.runtime.DisposableEffect import androidx.compose.runtime.Stable import androidx.compose.runtime.getValue import androidx.compose.runtime.mutableStateOf @@ -49,8 +48,6 @@ import androidx.compose.ui.res.stringResource import androidx.compose.ui.text.font.FontWeight import androidx.compose.ui.unit.DpSize import androidx.compose.ui.unit.dp -import androidx.lifecycle.Lifecycle -import androidx.lifecycle.LifecycleEventObserver import androidx.lifecycle.compose.collectAsStateWithLifecycle import coil.compose.AsyncImage import com.ramcosta.composedestinations.annotation.Destination @@ -82,7 +79,6 @@ import team.aliens.dms.android.core.ui.verticalPadding import team.aliens.dms.android.data.student.model.Student import team.aliens.dms.android.feature.R import team.aliens.dms.android.feature.outing.navigation.OutingNavigator -import java.util.UUID @OptIn(ExperimentalMaterial3Api::class) @Composable @@ -303,12 +299,11 @@ fun OutingApplicationScreen( val startTime = uiState.outingApplicationTime!!.startTime val endTime = uiState.outingApplicationTime!!.endTime FloatingNotice( + modifier = Modifier.horizontalPadding(), text = stringResource( id = R.string.outing_format_application_time, - startTime.hour, - startTime.minute, - endTime.hour, - endTime.minute, + startTime, + endTime, ), ) } diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index aa4beedad..d7832fcaa 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -303,7 +303,7 @@ 외출 신청 외출 시간 선택 - 외출 신청 시간은 %02d:%02d ~ %02d:%02d 입니다 + 외출 신청 시간은 %s ~ %s 입니다 신청 내역 외출 신청하기 기숙사에서 생활하는 동안 밖에 다녀올 일이 있다면 외출을 신청해 보세요. diff --git a/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt b/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt index adc23c3cf..2da832e15 100644 --- a/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt +++ b/network/src/main/java/team/aliens/dms/android/network/outing/model/OutingAvailableTimeResponse.kt @@ -1,17 +1,14 @@ package team.aliens.dms.android.network.outing.model import com.google.gson.annotations.SerializedName -import org.threeten.bp.DayOfWeek -import org.threeten.bp.LocalDateTime -import java.util.UUID data class OutingAvailableTimeResponse( - @SerializedName("outing_available_time") val availableTimes: List, + @SerializedName("outing_available_times") val availableTimes: List, ) { - data class AvailableTimeResponse( + data class AvailableTimeResponse( @SerializedName("outing_available_time_id") val id: String, - @SerializedName("outing_time") val startTime: LocalDateTime, - @SerializedName("arrival_time") val endTime: LocalDateTime, + @SerializedName("outing_time") val startTime: String, + @SerializedName("arrival_time") val endTime: String, @SerializedName("enabled") val available: Boolean, @SerializedName("day_of_week") val dayOfWeek: String, ) From 29acc72fc8c6819974392b5d5383936153b089d6 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 14 Apr 2024 13:58:03 +0900 Subject: [PATCH 123/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20outing=20appl?= =?UTF-8?q?ication=20error?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/feature/outing/OutingApplicationScreen.kt | 4 ++++ .../team/aliens/dms/android/feature/outing/OutingViewModel.kt | 3 +++ feature/src/main/res/values/strings.xml | 1 + 3 files changed, 8 insertions(+) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt index 79d43ab4f..3d93257c3 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingApplicationScreen.kt @@ -268,6 +268,10 @@ fun OutingApplicationScreen( message = context.getString(R.string.outing_application_error_outing_type_not_selected), ) + OutingSideEffect.OutingApplicationTimeError -> toast.showErrorToast( + message = context.getString(R.string.outing_application_error_outing_application_time_error), + ) + is OutingSideEffect.OutingApplicationSuccess -> navigator.navigateUp() else -> {/* explicit blank */ } diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt index 93eb98efd..cae010d07 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt @@ -155,6 +155,8 @@ class OutingViewModel @Inject constructor( ), ) postSideEffect(OutingSideEffect.OutingApplicationSuccess(applicationId)) + }.onSuccess { + postSideEffect(OutingSideEffect.OutingApplicationTimeError) } } } @@ -247,4 +249,5 @@ sealed class OutingSideEffect : SideEffect() { data object CurrentAppliedOutingApplicationNotFound : OutingSideEffect() data object OutingTypeNotSelected : OutingSideEffect() class OutingApplicationSuccess(val applicationId: UUID) : OutingSideEffect() + data object OutingApplicationTimeError: OutingSideEffect() } diff --git a/feature/src/main/res/values/strings.xml b/feature/src/main/res/values/strings.xml index d7832fcaa..c161ed1ec 100644 --- a/feature/src/main/res/values/strings.xml +++ b/feature/src/main/res/values/strings.xml @@ -341,4 +341,5 @@ 로그인 화면으로 새로 고침 성공 + 외출 신청 시간이 아닙니다. \ No newline at end of file From c82e129c1afb1626dd0ef8b960e9330ad0ca68f1 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 14 Apr 2024 14:02:12 +0900 Subject: [PATCH 124/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20release=20ver?= =?UTF-8?q?sion?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index f9ab46fa4..6416ee50d 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -17,8 +17,8 @@ android { minSdk = libs.versions.minSdk.get().toInt() targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = 8 - versionName = "v1.2.2" + versionCode = 9 + versionName = "v1.3.0" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } From 68bf9aac33e75d6904eaf8c7984c7642add373cf Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 14 Apr 2024 22:14:37 +0900 Subject: [PATCH 125/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20=EC=99=B8?= =?UTF-8?q?=EC=B6=9C=20=EC=8B=A0=EC=B2=AD=20=EC=8B=9C=EA=B0=84=20if=20?= =?UTF-8?q?=EC=B2=B4=ED=81=AC?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/feature/outing/OutingViewModel.kt | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt index cae010d07..d2bafdec4 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingViewModel.kt @@ -54,11 +54,13 @@ class OutingViewModel @Inject constructor( runCatching { outingRepository.fetchOutingApplicationTimes(dayOfWeek = today.dayOfWeek) }.onSuccess { fetchedApplicationTime -> - reduce( - newState = stateFlow.value.copy( - outingApplicationTime = fetchedApplicationTime.first(), - ), - ) + if (fetchedApplicationTime.isNotEmpty()) { + reduce( + newState = stateFlow.value.copy( + outingApplicationTime = fetchedApplicationTime.first(), + ), + ) + } }.onFailure { it.printStackTrace() } @@ -249,5 +251,5 @@ sealed class OutingSideEffect : SideEffect() { data object CurrentAppliedOutingApplicationNotFound : OutingSideEffect() data object OutingTypeNotSelected : OutingSideEffect() class OutingApplicationSuccess(val applicationId: UUID) : OutingSideEffect() - data object OutingApplicationTimeError: OutingSideEffect() + data object OutingApplicationTimeError : OutingSideEffect() } From f830320ae75e88719aa94f6a51dc16fa5c860f71 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Sun, 14 Apr 2024 22:52:20 +0900 Subject: [PATCH 126/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20=EB=B0=B0?= =?UTF-8?q?=ED=8F=AC=20=EB=B2=84=EC=A0=84=20=EC=97=85=EB=8D=B0=EC=9D=B4?= =?UTF-8?q?=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index 6416ee50d..e6ac722b3 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -17,8 +17,8 @@ android { minSdk = libs.versions.minSdk.get().toInt() targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = 9 - versionName = "v1.3.0" + versionCode = 10 + versionName = "v1.3.1" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" } From 517941773c4631825f88edaa298cfa647f9c11b8 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 16 Apr 2024 19:46:36 +0900 Subject: [PATCH 127/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20=EC=83=89?= =?UTF-8?q?=EC=83=81=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../dms/android/feature/main/mypage/MyPageScreen.kt | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt index 23b9e8ce1..1dbbfd293 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt @@ -389,20 +389,20 @@ private enum class PointCardType { val containerColor: Color @Composable inline get() = when (this) { - BONUS -> DmsTheme.colorScheme.primaryContainer - MINUS -> DmsTheme.colorScheme.errorContainer + BONUS -> DmsTheme.colorScheme.background + MINUS -> DmsTheme.colorScheme.background } val contentColor: Color @Composable inline get() = when (this) { - BONUS -> DmsTheme.colorScheme.onPrimaryContainer - MINUS -> DmsTheme.colorScheme.onErrorContainer + BONUS -> DmsTheme.colorScheme.error + MINUS -> DmsTheme.colorScheme.primary } val borderColor: Color @Composable inline get() = when (this) { - BONUS -> DmsTheme.colorScheme.onPrimaryContainer - MINUS -> DmsTheme.colorScheme.onErrorContainer + BONUS -> DmsTheme.colorScheme.error + MINUS -> DmsTheme.colorScheme.primary } val text: String From c1a95c27bd157f08805e6e179dd514b7ccac26dd Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 16 Apr 2024 20:01:07 +0900 Subject: [PATCH 128/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20shadow=20?= =?UTF-8?q?=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../aliens/dms/android/core/designsystem/Shadows.kt | 12 ++++++++---- .../aliens/dms/android/core/ui/PaddingDefaults.kt | 2 +- .../main/announcement/AnnouncementListScreen.kt | 5 +++-- .../feature/main/application/ApplicationScreen.kt | 7 ++++--- .../dms/android/feature/main/home/HomeScreen.kt | 10 +++++++--- .../dms/android/feature/main/mypage/MyPageScreen.kt | 11 +++++++---- .../dms/android/feature/outing/OutingStatusScreen.kt | 6 +++--- .../dms/android/feature/point/PointHistoryScreen.kt | 6 +++--- .../feature/remains/RemainsApplicationScreen.kt | 12 +++--------- .../aliens/dms/android/feature/studyroom/Common.kt | 6 +++--- 10 files changed, 42 insertions(+), 35 deletions(-) diff --git a/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Shadows.kt b/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Shadows.kt index 48ff45cf3..4f25bc481 100644 --- a/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Shadows.kt +++ b/core/design-system/src/main/java/team/aliens/dms/android/core/designsystem/Shadows.kt @@ -10,7 +10,7 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp fun Modifier.shadow( - elevation: Dp = ShadowDefaults.SmallElevation, + elevation: Dp = ShadowDefaults.MediumElevation, shape: Shape = ShadowDefaults.RoundedShape, clip: Boolean = elevation > 0.dp, ambientColor: Color? = null, @@ -20,8 +20,10 @@ fun Modifier.shadow( elevation = elevation, shape = shape, clip = clip, - ambientColor = ambientColor ?: DmsTheme.colorScheme.surfaceVariant, - spotColor = spotColor ?: DmsTheme.colorScheme.surfaceVariant, + ambientColor = ambientColor + ?: DmsTheme.colorScheme.onSurfaceVariant.copy(alpha = ShadowDefaults.DefaultAlpha), + spotColor = spotColor + ?: DmsTheme.colorScheme.onSurfaceVariant.copy(alpha = ShadowDefaults.DefaultAlpha), ) } @@ -30,5 +32,7 @@ object ShadowDefaults { val MediumElevation = 4.dp val LargeElevation = 8.dp - val RoundedShape = RoundedCornerShape(8.dp) + const val DefaultAlpha = 0.6f + + val RoundedShape = RoundedCornerShape(12.dp) } diff --git a/core/ui/src/main/java/team/aliens/dms/android/core/ui/PaddingDefaults.kt b/core/ui/src/main/java/team/aliens/dms/android/core/ui/PaddingDefaults.kt index 727061865..e67241ff9 100644 --- a/core/ui/src/main/java/team/aliens/dms/android/core/ui/PaddingDefaults.kt +++ b/core/ui/src/main/java/team/aliens/dms/android/core/ui/PaddingDefaults.kt @@ -97,7 +97,7 @@ fun Modifier.bottomPadding( value: Dp = PaddingDefaults.Medium, ): Modifier = padding(bottom = value) -val DefaultVerticalSpace = PaddingDefaults.Small +val DefaultVerticalSpace = PaddingDefaults.Medium val LargeVerticalSpace = PaddingDefaults.Medium diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/announcement/AnnouncementListScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/announcement/AnnouncementListScreen.kt index e3734d334..c3d97aa95 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/announcement/AnnouncementListScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/announcement/AnnouncementListScreen.kt @@ -29,6 +29,7 @@ import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.OutlinedButton import team.aliens.dms.android.core.designsystem.ShadowDefaults import team.aliens.dms.android.core.designsystem.clickable +import team.aliens.dms.android.core.designsystem.shadow import team.aliens.dms.android.core.ui.DefaultVerticalSpace import team.aliens.dms.android.core.ui.PaddingDefaults import team.aliens.dms.android.core.ui.bottomPadding @@ -144,13 +145,13 @@ private fun NoticeCard( Card( modifier = modifier .horizontalPadding() - .verticalPadding(PaddingDefaults.ExtraSmall), + .verticalPadding(PaddingDefaults.ExtraSmall) + .shadow(), shape = DmsTheme.shapes.surfaceSmall, colors = CardDefaults.cardColors( containerColor = DmsTheme.colorScheme.surface, contentColor = DmsTheme.colorScheme.onSurface, ), - elevation = CardDefaults.outlinedCardElevation(defaultElevation = ShadowDefaults.SmallElevation), ) { Column( modifier = Modifier diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt index 2b6b026d1..01e13dfbc 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/application/ApplicationScreen.kt @@ -31,6 +31,7 @@ import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.RoundedButton import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.ShadowDefaults +import team.aliens.dms.android.core.designsystem.shadow import team.aliens.dms.android.core.ui.DefaultVerticalSpace import team.aliens.dms.android.core.ui.PaddingDefaults import team.aliens.dms.android.core.ui.bottomPadding @@ -110,13 +111,13 @@ private fun ApplicationCard( modifier = modifier .animateContentSize() .horizontalPadding() - .verticalPadding(), + .verticalPadding() + .shadow(), shape = DmsTheme.shapes.surfaceSmall, - colors = CardDefaults.cardColors( + colors = CardDefaults.elevatedCardColors( containerColor = DmsTheme.colorScheme.surface, contentColor = DmsTheme.colorScheme.onSurface, ), - elevation = CardDefaults.outlinedCardElevation(defaultElevation = ShadowDefaults.SmallElevation), ) { Column( verticalArrangement = Arrangement.spacedBy(DefaultVerticalSpace), diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/home/HomeScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/home/HomeScreen.kt index d6005b7f0..f6ec86009 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/home/HomeScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/home/HomeScreen.kt @@ -67,16 +67,17 @@ import org.threeten.bp.DayOfWeek import org.threeten.bp.LocalDate import team.aliens.dms.android.core.designsystem.ButtonDefaults import team.aliens.dms.android.core.designsystem.DmsCalendar -import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.LocalToast import team.aliens.dms.android.core.designsystem.ModalBottomSheet import team.aliens.dms.android.core.designsystem.OutlinedButton import team.aliens.dms.android.core.designsystem.PrimaryDefault +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.ShadowDefaults import team.aliens.dms.android.core.designsystem.TextButton import team.aliens.dms.android.core.designsystem.clickable +import team.aliens.dms.android.core.designsystem.shadow import team.aliens.dms.android.core.ui.DefaultHorizontalSpace import team.aliens.dms.android.core.ui.DefaultVerticalSpace import team.aliens.dms.android.core.ui.PaddingDefaults @@ -546,7 +547,11 @@ private fun MealCard( } } } - }, + } + .shadow( + ambientColor = DmsTheme.colorScheme.primary.copy(alpha = ShadowDefaults.DefaultAlpha), + spotColor = DmsTheme.colorScheme.primary.copy(alpha = ShadowDefaults.DefaultAlpha), + ), shape = DmsTheme.shapes.surfaceLarge, colors = CardDefaults.outlinedCardColors( containerColor = DmsTheme.colorScheme.surface, @@ -556,7 +561,6 @@ private fun MealCard( width = 1.dp, color = DmsTheme.colorScheme.primary, ), - elevation = CardDefaults.outlinedCardElevation(defaultElevation = ShadowDefaults.SmallElevation), ) { val dishes = when (currentCardType) { BREAKFAST -> breakfast diff --git a/feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt index 1dbbfd293..bc410a4a7 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/main/mypage/MyPageScreen.kt @@ -36,14 +36,15 @@ import androidx.lifecycle.compose.collectAsStateWithLifecycle import com.ramcosta.composedestinations.annotation.Destination import team.aliens.dms.android.core.designsystem.AlertDialog import team.aliens.dms.android.core.designsystem.ButtonDefaults -import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.Gray10 import team.aliens.dms.android.core.designsystem.RoundedButton +import team.aliens.dms.android.core.designsystem.Scaffold import team.aliens.dms.android.core.designsystem.ShadowDefaults import team.aliens.dms.android.core.designsystem.TextButton import team.aliens.dms.android.core.designsystem.clickable +import team.aliens.dms.android.core.designsystem.shadow import team.aliens.dms.android.core.ui.DefaultHorizontalSpace import team.aliens.dms.android.core.ui.LargeVerticalSpace import team.aliens.dms.android.core.ui.PaddingDefaults @@ -385,7 +386,8 @@ private fun PointCard( @Immutable private enum class PointCardType { - BONUS, MINUS, ; + BONUS, MINUS, + ; val containerColor: Color @Composable inline get() = when (this) { @@ -493,13 +495,14 @@ private fun OptionLayout( titleColor: Color, ) { Card( - modifier = modifier.horizontalPadding(), + modifier = modifier + .horizontalPadding() + .shadow(), shape = DmsTheme.shapes.surfaceSmall, colors = CardDefaults.cardColors( containerColor = DmsTheme.colorScheme.surface, contentColor = titleColor, ), - elevation = CardDefaults.outlinedCardElevation(defaultElevation = ShadowDefaults.SmallElevation), ) { options.forEachIndexed { index, option -> Text( diff --git a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt index e095675a6..50e4c78c1 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/outing/OutingStatusScreen.kt @@ -38,8 +38,8 @@ import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.LocalToast import team.aliens.dms.android.core.designsystem.Scaffold -import team.aliens.dms.android.core.designsystem.ShadowDefaults import team.aliens.dms.android.core.designsystem.TextButton +import team.aliens.dms.android.core.designsystem.shadow import team.aliens.dms.android.core.ui.DefaultHorizontalSpace import team.aliens.dms.android.core.ui.DefaultVerticalSpace import team.aliens.dms.android.core.ui.PaddingDefaults @@ -176,13 +176,13 @@ private fun OutingInformationCard( Card( modifier = modifier .horizontalPadding() - .verticalPadding(PaddingDefaults.ExtraSmall), + .verticalPadding(PaddingDefaults.ExtraSmall) + .shadow(), shape = DmsTheme.shapes.surfaceMedium, colors = CardDefaults.cardColors( containerColor = DmsTheme.colorScheme.surface, contentColor = DmsTheme.colorScheme.onSurface, ), - elevation = CardDefaults.outlinedCardElevation(defaultElevation = ShadowDefaults.SmallElevation), ) { Column( modifier = Modifier.fillMaxWidth(), diff --git a/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt index 379861b04..a5e8d6912 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/point/PointHistoryScreen.kt @@ -28,8 +28,8 @@ import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.DmsTopAppBar import team.aliens.dms.android.core.designsystem.OutlinedButton import team.aliens.dms.android.core.designsystem.Scaffold -import team.aliens.dms.android.core.designsystem.ShadowDefaults import team.aliens.dms.android.core.designsystem.VerticallyFadedLazyColumn +import team.aliens.dms.android.core.designsystem.shadow import team.aliens.dms.android.core.ui.DefaultHorizontalSpace import team.aliens.dms.android.core.ui.DefaultVerticalSpace import team.aliens.dms.android.core.ui.PaddingDefaults @@ -174,13 +174,13 @@ private fun PointCard( Card( modifier = modifier .horizontalPadding() - .verticalPadding(PaddingDefaults.ExtraSmall), + .verticalPadding(PaddingDefaults.ExtraSmall) + .shadow(), shape = DmsTheme.shapes.surfaceSmall, colors = CardDefaults.cardColors( containerColor = DmsTheme.colorScheme.surface, contentColor = DmsTheme.colorScheme.onSurface, ), - elevation = CardDefaults.outlinedCardElevation(defaultElevation = ShadowDefaults.SmallElevation), ) { Column( verticalArrangement = Arrangement.spacedBy(DefaultVerticalSpace), diff --git a/feature/src/main/java/team/aliens/dms/android/feature/remains/RemainsApplicationScreen.kt b/feature/src/main/java/team/aliens/dms/android/feature/remains/RemainsApplicationScreen.kt index 60d324c3a..e5fa5ede6 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/remains/RemainsApplicationScreen.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/remains/RemainsApplicationScreen.kt @@ -42,6 +42,7 @@ import team.aliens.dms.android.core.designsystem.RoundedButton import team.aliens.dms.android.core.designsystem.ShadowDefaults import team.aliens.dms.android.core.designsystem.clickable import team.aliens.dms.android.core.designsystem.VerticallyFadedLazyColumn +import team.aliens.dms.android.core.designsystem.shadow import team.aliens.dms.android.core.ui.DefaultHorizontalSpace import team.aliens.dms.android.core.ui.PaddingDefaults import team.aliens.dms.android.core.ui.bottomPadding @@ -196,20 +197,13 @@ private fun RemainsOptionCard( Card( modifier = modifier .horizontalPadding() - .verticalPadding(PaddingDefaults.ExtraSmall), + .verticalPadding(PaddingDefaults.ExtraSmall) + .shadow(), shape = DmsTheme.shapes.surfaceSmall, colors = CardDefaults.cardColors( containerColor = DmsTheme.colorScheme.surface, contentColor = DmsTheme.colorScheme.onSurface, ), - elevation = CardDefaults.outlinedCardElevation( - defaultElevation = - if (selected) { - ShadowDefaults.MediumElevation - } else { - ShadowDefaults.SmallElevation - }, - ), border = if (selected) { BorderStroke( width = 1.dp, diff --git a/feature/src/main/java/team/aliens/dms/android/feature/studyroom/Common.kt b/feature/src/main/java/team/aliens/dms/android/feature/studyroom/Common.kt index 96a8ca147..65f3c5c3d 100644 --- a/feature/src/main/java/team/aliens/dms/android/feature/studyroom/Common.kt +++ b/feature/src/main/java/team/aliens/dms/android/feature/studyroom/Common.kt @@ -14,6 +14,7 @@ import androidx.compose.ui.Modifier import androidx.compose.ui.res.stringResource import team.aliens.dms.android.core.designsystem.DmsTheme import team.aliens.dms.android.core.designsystem.ShadowDefaults +import team.aliens.dms.android.core.designsystem.shadow import team.aliens.dms.android.core.ui.DefaultHorizontalSpace import team.aliens.dms.android.core.ui.PaddingDefaults import team.aliens.dms.android.core.ui.endPadding @@ -26,7 +27,6 @@ import team.aliens.dms.android.feature.R import team.aliens.dms.android.shared.model.Sex -@OptIn(ExperimentalMaterial3Api::class) @Composable fun StudyRoomCard( modifier: Modifier = Modifier, @@ -36,13 +36,13 @@ fun StudyRoomCard( Card( modifier = modifier .horizontalPadding() - .verticalPadding(PaddingDefaults.ExtraSmall), + .verticalPadding(PaddingDefaults.ExtraSmall) + .shadow(), shape = DmsTheme.shapes.surfaceSmall, colors = CardDefaults.cardColors( containerColor = DmsTheme.colorScheme.surface, contentColor = DmsTheme.colorScheme.onSurface, ), - elevation = CardDefaults.outlinedCardElevation(defaultElevation = ShadowDefaults.SmallElevation), onClick = onClick, ) { Column { From 4c57abc2f0d144722818c1642fdd19dcd8393561 Mon Sep 17 00:00:00 2001 From: junsuPark Date: Tue, 16 Apr 2024 20:03:29 +0900 Subject: [PATCH 129/129] =?UTF-8?q?=E2=99=BB=EF=B8=8F=20::=20=EB=B2=84?= =?UTF-8?q?=EC=A0=84=20=EC=97=85=EB=8D=B0=EC=9D=B4=ED=8A=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- app/build.gradle.kts | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/app/build.gradle.kts b/app/build.gradle.kts index e6ac722b3..068abf285 100644 --- a/app/build.gradle.kts +++ b/app/build.gradle.kts @@ -17,8 +17,8 @@ android { minSdk = libs.versions.minSdk.get().toInt() targetSdk = libs.versions.targetSdk.get().toInt() - versionCode = 10 - versionName = "v1.3.1" + versionCode = 11 + versionName = "v1.3.2" testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner" }