From 9e9e72dead691617008012a827041167d91688d6 Mon Sep 17 00:00:00 2001 From: beom84 Date: Thu, 16 Jan 2025 23:24:27 +0900 Subject: [PATCH 01/40] =?UTF-8?q?[add]=20#31=20ToDoCardModel=20isFinished?= =?UTF-8?q?=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/bbangzip/presentation/component/card/ToDoCard.kt | 4 ++++ .../android/bbangzip/presentation/model/card/ToDoCardModel.kt | 1 + 2 files changed, 5 insertions(+) diff --git a/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt b/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt index fa0929d2..7cbad292 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt @@ -205,6 +205,7 @@ fun ToDoCardPreview() { deadline = "2025년 4월 25일", pieceId = "1", remainingDays = 1, + isFinished = true ), modifier = Modifier @@ -222,6 +223,7 @@ fun ToDoCardPreview() { deadline = "2025년 4월 25일", pieceId = "1", remainingDays = 1, + isFinished = true ), modifier = Modifier @@ -239,6 +241,7 @@ fun ToDoCardPreview() { deadline = "2025년 4월 25일", pieceId = "1", remainingDays = 1, + isFinished = true ), modifier = Modifier @@ -256,6 +259,7 @@ fun ToDoCardPreview() { deadline = "2025년 4월 25일", pieceId = "1", remainingDays = 1, + isFinished = true ), modifier = Modifier diff --git a/app/src/main/java/org/android/bbangzip/presentation/model/card/ToDoCardModel.kt b/app/src/main/java/org/android/bbangzip/presentation/model/card/ToDoCardModel.kt index 90de955e..f126976a 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/model/card/ToDoCardModel.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/model/card/ToDoCardModel.kt @@ -13,4 +13,5 @@ data class ToDoCardModel( val finishPage: Int, val deadline: String, val remainingDays: Int, + val isFinished : Boolean, ) : Parcelable From 215e4da7d9549f46b780861144e708fefeb355b4 Mon Sep 17 00:00:00 2001 From: beom84 Date: Fri, 17 Jan 2025 03:59:39 +0900 Subject: [PATCH 02/40] =?UTF-8?q?[add]=20#31=20Todo=20Entity=20=EC=84=A0?= =?UTF-8?q?=EC=96=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bbangzip/domain/model/ToDoCardEntity.kt | 14 ++++++++++++++ .../bbangzip/domain/model/ToDoInfoEntity.kt | 8 ++++++++ .../presentation/model/card/ToDoCardModel.kt | 3 ++- 3 files changed, 24 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/org/android/bbangzip/domain/model/ToDoCardEntity.kt create mode 100644 app/src/main/java/org/android/bbangzip/domain/model/ToDoInfoEntity.kt diff --git a/app/src/main/java/org/android/bbangzip/domain/model/ToDoCardEntity.kt b/app/src/main/java/org/android/bbangzip/domain/model/ToDoCardEntity.kt new file mode 100644 index 00000000..9508697f --- /dev/null +++ b/app/src/main/java/org/android/bbangzip/domain/model/ToDoCardEntity.kt @@ -0,0 +1,14 @@ +package org.android.bbangzip.domain.model + + +data class ToDoCardEntity( + val pieceId: String, + val subjectName: String = "", + val examName: String = "", + val studyContents: String, + val startPage: Int, + val finishPage: Int, + val deadline: String, + val remainingDays: Int, + val isFinished : Boolean = false +) diff --git a/app/src/main/java/org/android/bbangzip/domain/model/ToDoInfoEntity.kt b/app/src/main/java/org/android/bbangzip/domain/model/ToDoInfoEntity.kt new file mode 100644 index 00000000..c64aee05 --- /dev/null +++ b/app/src/main/java/org/android/bbangzip/domain/model/ToDoInfoEntity.kt @@ -0,0 +1,8 @@ +package org.android.bbangzip.domain.model + +data class ToDoInfoEntity( + val todoList : List, + val pendingCount: Int, + val remainingStudyCount : Int, + val completeCount : Int, +) diff --git a/app/src/main/java/org/android/bbangzip/presentation/model/card/ToDoCardModel.kt b/app/src/main/java/org/android/bbangzip/presentation/model/card/ToDoCardModel.kt index f126976a..5303e5a2 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/model/card/ToDoCardModel.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/model/card/ToDoCardModel.kt @@ -2,6 +2,7 @@ package org.android.bbangzip.presentation.model.card import android.os.Parcelable import kotlinx.parcelize.Parcelize +import org.android.bbangzip.presentation.component.card.BbangZipCardState @Parcelize data class ToDoCardModel( @@ -13,5 +14,5 @@ data class ToDoCardModel( val finishPage: Int, val deadline: String, val remainingDays: Int, - val isFinished : Boolean, + val cardState: BbangZipCardState ) : Parcelable From 0559acfe8c9cf5fdf764878eb417c9e287e8279a Mon Sep 17 00:00:00 2001 From: beom84 Date: Fri, 17 Jan 2025 04:00:18 +0900 Subject: [PATCH 03/40] =?UTF-8?q?[add]=20#31=20ToDoCard=20state=20->=20ToD?= =?UTF-8?q?oCardModel=EC=9D=98=20cardState=EB=A1=9C=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/component/card/ToDoCard.kt | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt b/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt index 7cbad292..6b0d2234 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt @@ -33,12 +33,12 @@ import org.android.bbangzip.ui.theme.BbangZipTheme @Composable fun ToDoCard( - state: BbangZipCardState, data: ToDoCardModel, modifier: Modifier = Modifier, isDeleted: Boolean = false, onClick: () -> Unit = {}, ) { + val state = data.cardState val radius = state.getRadius() val infoOpacity = state.getInfoOpacity() Box( @@ -194,7 +194,6 @@ fun ToDoCardPreview() { BBANGZIPTheme { Column { ToDoCard( - state = BbangZipCardState.DEFAULT, data = ToDoCardModel( subjectName = "경제통계학개론", @@ -205,14 +204,13 @@ fun ToDoCardPreview() { deadline = "2025년 4월 25일", pieceId = "1", remainingDays = 1, - isFinished = true + cardState = BbangZipCardState.DEFAULT, ), modifier = Modifier .padding(16.dp), ) ToDoCard( - state = BbangZipCardState.CHECKABLE, data = ToDoCardModel( subjectName = "경제통계학개론", @@ -223,14 +221,13 @@ fun ToDoCardPreview() { deadline = "2025년 4월 25일", pieceId = "1", remainingDays = 1, - isFinished = true + cardState = BbangZipCardState.CHECKED, ), modifier = Modifier .padding(16.dp), ) ToDoCard( - state = BbangZipCardState.CHECKED, data = ToDoCardModel( subjectName = "경제통계학개론", @@ -241,14 +238,13 @@ fun ToDoCardPreview() { deadline = "2025년 4월 25일", pieceId = "1", remainingDays = 1, - isFinished = true + cardState = BbangZipCardState.CHECKABLE, ), modifier = Modifier .padding(16.dp), ) ToDoCard( - state = BbangZipCardState.COMPLETE, data = ToDoCardModel( subjectName = "경제통계학개론", @@ -259,7 +255,7 @@ fun ToDoCardPreview() { deadline = "2025년 4월 25일", pieceId = "1", remainingDays = 1, - isFinished = true + cardState = BbangZipCardState.COMPLETE, ), modifier = Modifier From 158df696b021f09d16e2c38c8ae4ebb87ecccfca Mon Sep 17 00:00:00 2001 From: beom84 Date: Fri, 17 Jan 2025 06:26:27 +0900 Subject: [PATCH 04/40] =?UTF-8?q?[feat]=20#31=20TodoContract=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bbangzip/domain/model/ToDoCardEntity.kt | 3 +- .../presentation/ui/todo/TodoContract.kt | 80 +++++++++++++++++++ 2 files changed, 81 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt diff --git a/app/src/main/java/org/android/bbangzip/domain/model/ToDoCardEntity.kt b/app/src/main/java/org/android/bbangzip/domain/model/ToDoCardEntity.kt index 9508697f..4747edfe 100644 --- a/app/src/main/java/org/android/bbangzip/domain/model/ToDoCardEntity.kt +++ b/app/src/main/java/org/android/bbangzip/domain/model/ToDoCardEntity.kt @@ -1,6 +1,5 @@ package org.android.bbangzip.domain.model - data class ToDoCardEntity( val pieceId: String, val subjectName: String = "", @@ -10,5 +9,5 @@ data class ToDoCardEntity( val finishPage: Int, val deadline: String, val remainingDays: Int, - val isFinished : Boolean = false + val isFinished: Boolean = false, ) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt new file mode 100644 index 00000000..5d1086dd --- /dev/null +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt @@ -0,0 +1,80 @@ +package org.android.bbangzip.presentation.ui.todo + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize +import org.android.bbangzip.presentation.component.card.BbangZipCardState +import org.android.bbangzip.presentation.model.card.ToDoCardModel +import org.android.bbangzip.presentation.type.ToDoFilterType +import org.android.bbangzip.presentation.util.base.BaseContract + +class TodoContract { + @Parcelize + data class TodoState( + val todoList: List, + val pendingCount: Int, + val remainingStudyCount: Int, + val completeCount: Int, + val todoFilterBottomSheetState: Boolean, + val todoFilterItemIndex: Int, + val revertCompleteBottomSheetState: Boolean, + ) : BaseContract.State, Parcelable { + override fun toParcelable(): Parcelable = this + } + + sealed interface TodoEvent : BaseContract.Event { + data object Initialize : TodoEvent + + data object OnPendingStudyButtonClicked : TodoEvent + + data object OnAddStudyButtonClicked : TodoEvent + + data object OnFilterDismissRequest : TodoEvent + + data object OnRevertCompleteDismissButtonClicked : TodoEvent + + data object OnRevertCompleteDismissRequest : TodoEvent + + data object OnFilterIconClicked : TodoEvent + + data object OnDeleteIconClicked : TodoEvent + + data object OnCloseIconClicked : TodoEvent + + data class OnItemDeleteButtonClicked(val pieceIds: List) : TodoEvent + + data class FetchToDoInfo( + val year: Int, + val semester: String, + val sortOption: String = ToDoFilterType.RECENT.id, + ) : TodoEvent + + data class OnFilterItemClicked(val todoFilterItemIndex: Int) : TodoEvent + + data class OnRevertCompleteApproveButtonClicked(val pieceIds: List) : TodoEvent + } + + sealed interface TodoReduce : BaseContract.Reduce { + data class UpdateToDoInfo( + val todoList: List, + val pendingCount: Int, + val remainingStudyCount: Int, + val completeCount: Int, + ) : TodoReduce + + data class UpdateToDoFilterBottomSheetState(val todoFilterBottomSheetState: Boolean) + + data class UpdateRevertCompleteBottomSheetState(val revertCompleteBottomSheetState: Boolean) + + data class UpdateToDoCount(val completeCount: Int, val remainingStudyCount: Int) + + data class UpdateCardState(val cardState: BbangZipCardState) + } + + sealed interface TodoSideEffect : BaseContract.SideEffect { + data object NavigateToAddToDo : TodoSideEffect + + data object NavigateToAddPendingToDo : TodoSideEffect + + data class ShowSnackBar(val message: String) : TodoSideEffect + } +} From 9ab6d20e6934e061e9b840abbfc0a92efa9cadb3 Mon Sep 17 00:00:00 2001 From: beom84 Date: Fri, 17 Jan 2025 06:28:03 +0900 Subject: [PATCH 05/40] =?UTF-8?q?[feat]=20#31=20ToDoFilterType=20=EC=B6=94?= =?UTF-8?q?=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/model/card/ToDoCardModel.kt | 2 +- .../presentation/type/ToDoFilterType.kt | 22 +++++++++++++++++++ app/src/main/res/values/strings.xml | 5 +++++ 3 files changed, 28 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/org/android/bbangzip/presentation/type/ToDoFilterType.kt diff --git a/app/src/main/java/org/android/bbangzip/presentation/model/card/ToDoCardModel.kt b/app/src/main/java/org/android/bbangzip/presentation/model/card/ToDoCardModel.kt index 5303e5a2..966195d3 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/model/card/ToDoCardModel.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/model/card/ToDoCardModel.kt @@ -14,5 +14,5 @@ data class ToDoCardModel( val finishPage: Int, val deadline: String, val remainingDays: Int, - val cardState: BbangZipCardState + val cardState: BbangZipCardState, ) : Parcelable diff --git a/app/src/main/java/org/android/bbangzip/presentation/type/ToDoFilterType.kt b/app/src/main/java/org/android/bbangzip/presentation/type/ToDoFilterType.kt new file mode 100644 index 00000000..ff197792 --- /dev/null +++ b/app/src/main/java/org/android/bbangzip/presentation/type/ToDoFilterType.kt @@ -0,0 +1,22 @@ +package org.android.bbangzip.presentation.type + +import androidx.annotation.StringRes +import org.android.bbangzip.R + +enum class ToDoFilterType( + @StringRes val filter: Int, + val id: String, +) { + RECENT( + filter = R.string.todo_filter_recent, + id = "recent", + ), + VOLUME( + filter = R.string.todo_filter_least_volume, + id = "leastVolume", + ), + DEADLINE( + filter = R.string.todo_filter_deadline, + id = "nearestDeadline", + ), +} diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 8f1ef473..cf961a34 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -64,4 +64,9 @@ %s 사장님, 안녕하세요! 수강하는 과목 중 한 가지만 먼저 입력해 볼까요? >%s %s에 재학 중이시네요! + + + recent + leastVolume + nearestDeadline \ No newline at end of file From d8f63f347a897973053c13e0c796613145153fc6 Mon Sep 17 00:00:00 2001 From: beom84 Date: Fri, 17 Jan 2025 15:24:15 +0900 Subject: [PATCH 06/40] [add] #31 ToDoEntity ,Model pieceId String -> Int --- .../java/org/android/bbangzip/domain/model/ToDoCardEntity.kt | 2 +- .../android/bbangzip/presentation/model/card/ToDoCardModel.kt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/domain/model/ToDoCardEntity.kt b/app/src/main/java/org/android/bbangzip/domain/model/ToDoCardEntity.kt index 4747edfe..bae34da7 100644 --- a/app/src/main/java/org/android/bbangzip/domain/model/ToDoCardEntity.kt +++ b/app/src/main/java/org/android/bbangzip/domain/model/ToDoCardEntity.kt @@ -1,7 +1,7 @@ package org.android.bbangzip.domain.model data class ToDoCardEntity( - val pieceId: String, + val pieceId: Int, val subjectName: String = "", val examName: String = "", val studyContents: String, diff --git a/app/src/main/java/org/android/bbangzip/presentation/model/card/ToDoCardModel.kt b/app/src/main/java/org/android/bbangzip/presentation/model/card/ToDoCardModel.kt index 966195d3..74dd0920 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/model/card/ToDoCardModel.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/model/card/ToDoCardModel.kt @@ -6,7 +6,7 @@ import org.android.bbangzip.presentation.component.card.BbangZipCardState @Parcelize data class ToDoCardModel( - val pieceId: String, + val pieceId: Int, val subjectName: String, val examName: String, val studyContents: String, From faa96a5e6f7f1195a44972ef700a812df8ba6ad0 Mon Sep 17 00:00:00 2001 From: beom84 Date: Fri, 17 Jan 2025 16:33:53 +0900 Subject: [PATCH 07/40] =?UTF-8?q?[feat]=20#31=20ToDoViewModel=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/component/card/ToDoCard.kt | 8 +- .../presentation/type/ToDoScreenType.kt | 7 + .../presentation/ui/todo/TodoContract.kt | 68 ++++++--- .../presentation/ui/todo/TodoViewModel.kt | 143 ++++++++++++++++++ 4 files changed, 205 insertions(+), 21 deletions(-) create mode 100644 app/src/main/java/org/android/bbangzip/presentation/type/ToDoScreenType.kt create mode 100644 app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt diff --git a/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt b/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt index 6b0d2234..5c43f2b1 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt @@ -202,7 +202,7 @@ fun ToDoCardPreview() { startPage = 36, finishPage = 60, deadline = "2025년 4월 25일", - pieceId = "1", + pieceId = 1, remainingDays = 1, cardState = BbangZipCardState.DEFAULT, ), @@ -219,7 +219,7 @@ fun ToDoCardPreview() { startPage = 36, finishPage = 60, deadline = "2025년 4월 25일", - pieceId = "1", + pieceId = 1, remainingDays = 1, cardState = BbangZipCardState.CHECKED, ), @@ -236,7 +236,7 @@ fun ToDoCardPreview() { startPage = 36, finishPage = 60, deadline = "2025년 4월 25일", - pieceId = "1", + pieceId = 1, remainingDays = 1, cardState = BbangZipCardState.CHECKABLE, ), @@ -253,7 +253,7 @@ fun ToDoCardPreview() { startPage = 36, finishPage = 60, deadline = "2025년 4월 25일", - pieceId = "1", + pieceId = 1, remainingDays = 1, cardState = BbangZipCardState.COMPLETE, ), diff --git a/app/src/main/java/org/android/bbangzip/presentation/type/ToDoScreenType.kt b/app/src/main/java/org/android/bbangzip/presentation/type/ToDoScreenType.kt new file mode 100644 index 00000000..d6274b64 --- /dev/null +++ b/app/src/main/java/org/android/bbangzip/presentation/type/ToDoScreenType.kt @@ -0,0 +1,7 @@ +package org.android.bbangzip.presentation.type + +enum class ToDoScreenType { + EMPTY, + FETCH, + DELETE +} \ No newline at end of file diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt index 5d1086dd..aa3a481a 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt @@ -5,18 +5,21 @@ import kotlinx.parcelize.Parcelize import org.android.bbangzip.presentation.component.card.BbangZipCardState import org.android.bbangzip.presentation.model.card.ToDoCardModel import org.android.bbangzip.presentation.type.ToDoFilterType +import org.android.bbangzip.presentation.type.ToDoScreenType import org.android.bbangzip.presentation.util.base.BaseContract class TodoContract { @Parcelize data class TodoState( - val todoList: List, - val pendingCount: Int, - val remainingStudyCount: Int, - val completeCount: Int, - val todoFilterBottomSheetState: Boolean, - val todoFilterItemIndex: Int, - val revertCompleteBottomSheetState: Boolean, + val todoList: List = listOf(), + val pendingCount: Int = 0, + val remainingStudyCount: Int = 0, + val completeCount: Int = 0, + val todoFilterBottomSheetState: Boolean = false, + val todoFilterItemIndex: Int = 0, + val selectedItemList : List = listOf(), + val revertCompleteBottomSheetState: Boolean = false, + val screenType: ToDoScreenType = ToDoScreenType.EMPTY ) : BaseContract.State, Parcelable { override fun toParcelable(): Parcelable = this } @@ -24,7 +27,7 @@ class TodoContract { sealed interface TodoEvent : BaseContract.Event { data object Initialize : TodoEvent - data object OnPendingStudyButtonClicked : TodoEvent + data object OnAddPendingStudyButtonClicked : TodoEvent data object OnAddStudyButtonClicked : TodoEvent @@ -40,17 +43,24 @@ class TodoContract { data object OnCloseIconClicked : TodoEvent - data class OnItemDeleteButtonClicked(val pieceIds: List) : TodoEvent + data object OnItemDeleteButtonClicked : TodoEvent + + data class OnRevertCompleteApproveButtonClicked( + val pieceId: Int, + val cardState: BbangZipCardState + ) : TodoEvent data class FetchToDoInfo( - val year: Int, - val semester: String, - val sortOption: String = ToDoFilterType.RECENT.id, + val todoList: List, + val pendingCount: Int, + val remainingStudyCount: Int, + val completeCount: Int ) : TodoEvent data class OnFilterItemClicked(val todoFilterItemIndex: Int) : TodoEvent - data class OnRevertCompleteApproveButtonClicked(val pieceIds: List) : TodoEvent + data class OnDeleteScreenCardClicked(val pieceId: Int) : TodoEvent + } sealed interface TodoReduce : BaseContract.Reduce { @@ -61,13 +71,37 @@ class TodoContract { val completeCount: Int, ) : TodoReduce - data class UpdateToDoFilterBottomSheetState(val todoFilterBottomSheetState: Boolean) + data class UpdateToDoFilterBottomSheetState(val todoFilterBottomSheetState: Boolean) : + TodoReduce + + data class UpdateRevertCompleteBottomSheetState(val revertCompleteBottomSheetState: Boolean) : + TodoReduce + + data class UpdateToDoCount(val completeCount: Int, val remainingStudyCount: Int) : + TodoReduce + + data class UpdateCardState( + val pieceId: Int, + val cardState: BbangZipCardState + ) : TodoReduce + + data class UpdateToDoListState( + val cardState: BbangZipCardState + ) : TodoReduce + + data class UpdateFilterItemIndex( + val itemIndex: Int + ) : TodoReduce + + data class DeleteToDoListItems( + val pieceIds: List + ) : TodoReduce - data class UpdateRevertCompleteBottomSheetState(val revertCompleteBottomSheetState: Boolean) + data class UpdatePendingToDoCount(val pendingCount: Int) : TodoReduce - data class UpdateToDoCount(val completeCount: Int, val remainingStudyCount: Int) + data class UpdateScreenType(val screenType: ToDoScreenType) : TodoReduce - data class UpdateCardState(val cardState: BbangZipCardState) + data class UpdateSelectedItemList(val pieceId: Int) : TodoReduce } sealed interface TodoSideEffect : BaseContract.SideEffect { diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt new file mode 100644 index 00000000..8bc0f402 --- /dev/null +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt @@ -0,0 +1,143 @@ +package org.android.bbangzip.presentation.ui.todo + +import android.os.Parcelable +import androidx.lifecycle.SavedStateHandle +import dagger.hilt.android.lifecycle.HiltViewModel +import org.android.bbangzip.presentation.type.ToDoScreenType +import org.android.bbangzip.presentation.util.base.BaseViewModel +import javax.inject.Inject + +@HiltViewModel +class TodoViewModel +@Inject +constructor( + savedStateHandle: SavedStateHandle, +) : BaseViewModel( + savedStateHandle = savedStateHandle, +) { + override fun createInitialState(savedState: Parcelable?): TodoContract.TodoState = TodoContract.TodoState() + + init { + setEvent(TodoContract.TodoEvent.Initialize) + } + + override fun handleEvent(event: TodoContract.TodoEvent) { + when (event) { + //ToDoInfo Fetch + is TodoContract.TodoEvent.FetchToDoInfo -> updateState( + TodoContract.TodoReduce.UpdateToDoInfo( + pendingCount = event.pendingCount, + remainingStudyCount = event.remainingStudyCount, + completeCount = event.completeCount, + todoList = event.todoList + ) + ) + + TodoContract.TodoEvent.Initialize -> launch { initDataLoad() } + + //Filter BottomSheet + is TodoContract.TodoEvent.OnFilterItemClicked -> updateState( + TodoContract.TodoReduce.UpdateFilterItemIndex(itemIndex = event.todoFilterItemIndex) + ) + + TodoContract.TodoEvent.OnFilterDismissRequest -> updateState(TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState(todoFilterBottomSheetState = false)) + TodoContract.TodoEvent.OnFilterIconClicked -> updateState(TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState(todoFilterBottomSheetState = true)) + + //revertComplete BottomSheet + is TodoContract.TodoEvent.OnRevertCompleteApproveButtonClicked -> { + updateState(TodoContract.TodoReduce.UpdateCardState(pieceId = event.pieceId, cardState = event.cardState)) + updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = false)) + } + + TodoContract.TodoEvent.OnRevertCompleteDismissButtonClicked -> updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = false)) + TodoContract.TodoEvent.OnRevertCompleteDismissRequest -> updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = false)) + + //Delete + is TodoContract.TodoEvent.OnDeleteScreenCardClicked -> + updateState(TodoContract.TodoReduce.UpdateSelectedItemList(pieceId = event.pieceId)) + + + TodoContract.TodoEvent.OnDeleteIconClicked -> updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.DELETE)) + TodoContract.TodoEvent.OnItemDeleteButtonClicked -> updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = true)) + TodoContract.TodoEvent.OnCloseIconClicked -> updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.FETCH)) + + //화면 이동 + TodoContract.TodoEvent.OnAddStudyButtonClicked -> setSideEffect(TodoContract.TodoSideEffect.NavigateToAddToDo) + TodoContract.TodoEvent.OnAddPendingStudyButtonClicked -> setSideEffect(TodoContract.TodoSideEffect.NavigateToAddPendingToDo) + } + } + + override fun reduceState(state: TodoContract.TodoState, reduce: TodoContract.TodoReduce): TodoContract.TodoState { + return when (reduce) { + //ToDoInfo Fetch + is TodoContract.TodoReduce.UpdateToDoInfo -> state.copy( + pendingCount = reduce.pendingCount, + completeCount = reduce.completeCount, + remainingStudyCount = reduce.remainingStudyCount, + todoList = reduce.todoList + ) + + //List + is TodoContract.TodoReduce.UpdateCardState -> state.copy( + todoList = state.todoList.map { item -> + if (item.pieceId == reduce.pieceId) item.copy(cardState = reduce.cardState) else item + } + ) + + is TodoContract.TodoReduce.UpdateToDoListState -> state.copy( + todoList = state.todoList.map { item -> + item.copy(cardState = reduce.cardState) + } + ) + + is TodoContract.TodoReduce.DeleteToDoListItems -> { + val pieceIdSet = reduce.pieceIds.toSet() + state.copy( + todoList = state.todoList.filter { item -> + item.pieceId !in pieceIdSet + } + ) + } + + //Revert BottomSheet + is TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState -> state.copy( + revertCompleteBottomSheetState = !state.revertCompleteBottomSheetState + ) + + is TodoContract.TodoReduce.UpdateSelectedItemList -> state.copy( + selectedItemList = state.selectedItemList.plus(reduce.pieceId) + ) + + //Filter BottomSheet + is TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState -> state.copy( + todoFilterBottomSheetState = !state.todoFilterBottomSheetState + ) + + is TodoContract.TodoReduce.UpdateFilterItemIndex -> state.copy( + todoFilterItemIndex = reduce.itemIndex + ) + + //ToDoCount + is TodoContract.TodoReduce.UpdateToDoCount -> state.copy( + completeCount = reduce.completeCount, remainingStudyCount = reduce.remainingStudyCount + ) + + is TodoContract.TodoReduce.UpdatePendingToDoCount -> state.copy( + pendingCount = reduce.pendingCount + ) + + //ScreenType + is TodoContract.TodoReduce.UpdateScreenType -> state.copy( + screenType = reduce.screenType + ) + + + } + } + + private suspend fun initDataLoad() { + + } + + +} \ No newline at end of file From bf8be9d4c55dfe611f42e0531ed1c63f59925adc Mon Sep 17 00:00:00 2001 From: beom84 Date: Fri, 17 Jan 2025 19:08:04 +0900 Subject: [PATCH 08/40] =?UTF-8?q?[chore]=20#31=20ToDoEvent=20=ED=95=A8?= =?UTF-8?q?=EC=88=98=20=EB=84=A4=EC=9D=B4=EB=B0=8D=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bbangzip/presentation/ui/todo/TodoViewModel.kt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt index 8bc0f402..8ee6b5e9 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt @@ -36,21 +36,21 @@ constructor( TodoContract.TodoEvent.Initialize -> launch { initDataLoad() } //Filter BottomSheet - is TodoContract.TodoEvent.OnFilterItemClicked -> updateState( + is TodoContract.TodoEvent.OnFilterBottomSheetItemClicked -> updateState( TodoContract.TodoReduce.UpdateFilterItemIndex(itemIndex = event.todoFilterItemIndex) ) - TodoContract.TodoEvent.OnFilterDismissRequest -> updateState(TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState(todoFilterBottomSheetState = false)) + TodoContract.TodoEvent.OnFilterBottomSheetDismissRequest -> updateState(TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState(todoFilterBottomSheetState = false)) TodoContract.TodoEvent.OnFilterIconClicked -> updateState(TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState(todoFilterBottomSheetState = true)) //revertComplete BottomSheet - is TodoContract.TodoEvent.OnRevertCompleteApproveButtonClicked -> { + is TodoContract.TodoEvent.OnRevertCompleteBottomSheetApproveButtonClicked -> { updateState(TodoContract.TodoReduce.UpdateCardState(pieceId = event.pieceId, cardState = event.cardState)) updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = false)) } - TodoContract.TodoEvent.OnRevertCompleteDismissButtonClicked -> updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = false)) - TodoContract.TodoEvent.OnRevertCompleteDismissRequest -> updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = false)) + TodoContract.TodoEvent.OnRevertCompleteBottomSheetDismissButtonClicked -> updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = false)) + TodoContract.TodoEvent.OnRevertCompleteBottomSheetDismissRequest -> updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = false)) //Delete is TodoContract.TodoEvent.OnDeleteScreenCardClicked -> From 672b7078bd9d199bd363605170ecc22c0ddad552 Mon Sep 17 00:00:00 2001 From: beom84 Date: Fri, 17 Jan 2025 19:08:57 +0900 Subject: [PATCH 09/40] =?UTF-8?q?[feat]=20#31=20snackbarHostState=20?= =?UTF-8?q?=ED=98=B8=EC=9D=B4=EC=8A=A4=ED=8C=85?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/ui/navigator/MainNavHost.kt | 2 +- .../bbangzip/presentation/ui/todo/TodoContract.kt | 13 ++++++------- .../bbangzip/presentation/ui/todo/TodoNavigation.kt | 5 +++-- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt index cb7c531b..080dc79e 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt @@ -40,7 +40,7 @@ fun MainNavHost( subjectNavGraph() - todoNavGraph() + todoNavGraph(snackBarHostState = snackBarHostState) dummyNavGraph() } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt index aa3a481a..f4220116 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt @@ -4,7 +4,6 @@ import android.os.Parcelable import kotlinx.parcelize.Parcelize import org.android.bbangzip.presentation.component.card.BbangZipCardState import org.android.bbangzip.presentation.model.card.ToDoCardModel -import org.android.bbangzip.presentation.type.ToDoFilterType import org.android.bbangzip.presentation.type.ToDoScreenType import org.android.bbangzip.presentation.util.base.BaseContract @@ -17,7 +16,7 @@ class TodoContract { val completeCount: Int = 0, val todoFilterBottomSheetState: Boolean = false, val todoFilterItemIndex: Int = 0, - val selectedItemList : List = listOf(), + val selectedItemList: List = listOf(), val revertCompleteBottomSheetState: Boolean = false, val screenType: ToDoScreenType = ToDoScreenType.EMPTY ) : BaseContract.State, Parcelable { @@ -31,11 +30,11 @@ class TodoContract { data object OnAddStudyButtonClicked : TodoEvent - data object OnFilterDismissRequest : TodoEvent + data object OnRevertCompleteBottomSheetDismissButtonClicked : TodoEvent - data object OnRevertCompleteDismissButtonClicked : TodoEvent + data object OnFilterBottomSheetDismissRequest : TodoEvent - data object OnRevertCompleteDismissRequest : TodoEvent + data object OnRevertCompleteBottomSheetDismissRequest : TodoEvent data object OnFilterIconClicked : TodoEvent @@ -45,7 +44,7 @@ class TodoContract { data object OnItemDeleteButtonClicked : TodoEvent - data class OnRevertCompleteApproveButtonClicked( + data class OnRevertCompleteBottomSheetApproveButtonClicked( val pieceId: Int, val cardState: BbangZipCardState ) : TodoEvent @@ -57,7 +56,7 @@ class TodoContract { val completeCount: Int ) : TodoEvent - data class OnFilterItemClicked(val todoFilterItemIndex: Int) : TodoEvent + data class OnFilterBottomSheetItemClicked(val todoFilterItemIndex: Int) : TodoEvent data class OnDeleteScreenCardClicked(val pieceId: Int) : TodoEvent diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoNavigation.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoNavigation.kt index b5a5253d..bacbc1cd 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoNavigation.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoNavigation.kt @@ -1,5 +1,6 @@ package org.android.bbangzip.presentation.ui.todo +import androidx.compose.material3.SnackbarHostState import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions @@ -13,8 +14,8 @@ fun NavController.navigateTodo(navOptions: NavOptions) { ) } -fun NavGraphBuilder.todoNavGraph() { +fun NavGraphBuilder.todoNavGraph(snackBarHostState: SnackbarHostState) { composable { - TodoRoute() + TodoRoute(snackBarHostState = snackBarHostState) } } From 341389608e86c11e5ef503faecae67bd566c1478 Mon Sep 17 00:00:00 2001 From: beom84 Date: Fri, 17 Jan 2025 19:09:11 +0900 Subject: [PATCH 10/40] =?UTF-8?q?[feat]=20#31=20Route=20=ED=95=A8=EC=88=98?= =?UTF-8?q?=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/ui/todo/TodoRoute.kt | 80 ++++++++++++++++++- .../presentation/ui/todo/TodoScreen.kt | 16 ++++ 2 files changed, 94 insertions(+), 2 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt index dfb21910..b80bc075 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt @@ -1,8 +1,84 @@ package org.android.bbangzip.presentation.ui.todo +import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import kotlinx.coroutines.flow.collectLatest @Composable -fun TodoRoute() { - TodoScreen() +fun TodoRoute( + snackBarHostState: SnackbarHostState, + navigateToAddToDo: () -> Unit = {}, + navigateToAddPendingToDo: () -> Unit = {}, + viewModel: TodoViewModel = hiltViewModel() +) { + val todoState by viewModel.uiState.collectAsStateWithLifecycle() + val success by viewModel.success.collectAsStateWithLifecycle(initialValue = false) + + LaunchedEffect(viewModel.uiSideEffect) { + viewModel.uiSideEffect.collectLatest { effect -> + when (effect) { + TodoContract.TodoSideEffect.NavigateToAddPendingToDo -> + navigateToAddPendingToDo() + + TodoContract.TodoSideEffect.NavigateToAddToDo -> + navigateToAddToDo() + + is TodoContract.TodoSideEffect.ShowSnackBar -> + snackBarHostState.showSnackbar(effect.message) + } + } + } + + when (success) { + true -> + TodoScreen( + todoState = todoState, + snackBarHostState = snackBarHostState, + onAddPendingStudyButtonClicked = { + viewModel.setEvent(TodoContract.TodoEvent.OnAddPendingStudyButtonClicked) + }, + onAddStudyButtonClicked = { + viewModel.setEvent(TodoContract.TodoEvent.OnAddStudyButtonClicked) + }, + onRevertCompleteBottomSheetDismissButtonClicked = { + viewModel.setEvent(TodoContract.TodoEvent.OnRevertCompleteBottomSheetDismissButtonClicked) + }, + onRevertCompleteBottomSheetApproveButtonClicked = { pieceId, cardState -> + viewModel.setEvent( + TodoContract.TodoEvent.OnRevertCompleteBottomSheetApproveButtonClicked(pieceId = pieceId, cardState = cardState) + ) + }, + onRevertCompleteBottomSheetDismissRequest = { + viewModel.setEvent(TodoContract.TodoEvent.OnFilterBottomSheetDismissRequest) + }, + onFilterIconClicked = { + viewModel.setEvent(TodoContract.TodoEvent.OnFilterIconClicked) + }, + onFilterBottomSheetItemClicked = { filterIndex -> + viewModel.setEvent(TodoContract.TodoEvent.OnFilterBottomSheetItemClicked(todoFilterItemIndex = filterIndex)) + }, + onFilterBottomSheetDismissRequest ={ + viewModel.setEvent(TodoContract.TodoEvent.OnFilterBottomSheetDismissRequest) + }, + onDeleteIconClicked ={ + viewModel.setEvent(TodoContract.TodoEvent.OnDeleteIconClicked) + }, + onCloseIconClicked = { + viewModel.setEvent(TodoContract.TodoEvent.OnCloseIconClicked) + }, + onItemDeleteButtonClicked ={ + viewModel.setEvent(TodoContract.TodoEvent.OnItemDeleteButtonClicked) + }, + onDeleteScreenCardClicked = { pieceId -> + viewModel.setEvent(TodoContract.TodoEvent.OnDeleteScreenCardClicked(pieceId = pieceId)) + }, + ) + + false -> + null + } } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt index 6abd9625..1554e0f8 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt @@ -1,12 +1,28 @@ package org.android.bbangzip.presentation.ui.todo +import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier +import org.android.bbangzip.presentation.component.card.BbangZipCardState @Composable fun TodoScreen( + todoState: TodoContract.TodoState, + snackBarHostState: SnackbarHostState, modifier: Modifier = Modifier, + onAddPendingStudyButtonClicked: () -> Unit = {}, + onAddStudyButtonClicked: () -> Unit = {}, + onRevertCompleteBottomSheetDismissButtonClicked: () -> Unit = {}, + onRevertCompleteBottomSheetApproveButtonClicked: (Int, BbangZipCardState) -> Unit = { _, _ -> }, + onRevertCompleteBottomSheetDismissRequest: () -> Unit = {}, + onFilterIconClicked: () -> Unit = {}, + onFilterBottomSheetItemClicked: (Int) -> Unit = {}, + onFilterBottomSheetDismissRequest: () -> Unit = {}, + onDeleteIconClicked: () -> Unit = {}, + onCloseIconClicked: () -> Unit = {}, + onItemDeleteButtonClicked: () -> Unit = {}, + onDeleteScreenCardClicked: (Int) -> Unit = {} ) { Text("todo 탭") } From 946c381e941c02ddf3c2e9369e8f398026a13513 Mon Sep 17 00:00:00 2001 From: beom84 Date: Fri, 17 Jan 2025 22:41:19 +0900 Subject: [PATCH 11/40] =?UTF-8?q?[fix]=20#31=20button=20type=20enable=20ba?= =?UTF-8?q?ckground=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/bbangzip/presentation/type/BbangZipButtonType.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/type/BbangZipButtonType.kt b/app/src/main/java/org/android/bbangzip/presentation/type/BbangZipButtonType.kt index 13bde7f3..f52a99b5 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/type/BbangZipButtonType.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/type/BbangZipButtonType.kt @@ -24,7 +24,7 @@ sealed class BbangZipButtonType( ) data object Outlined : BbangZipButtonType( - enableBackgroundColor = defaultBbangZipColors.staticWhite_FFFFFF, + enableBackgroundColor = Color.Transparent, enableContentColor = defaultBbangZipColors.primaryNormal_282119, enableBorderColor = defaultBbangZipColors.lineStrong_68645E_52, disableBackgroundColor = Color.Unspecified, From e5472ba529fd1f82876ae4fb712f6293649bc026 Mon Sep 17 00:00:00 2001 From: beom84 Date: Fri, 17 Jan 2025 22:42:05 +0900 Subject: [PATCH 12/40] =?UTF-8?q?[fix]=20#31=20button=20spacing=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bbangzip/presentation/component/button/BbangZipButton.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/component/button/BbangZipButton.kt b/app/src/main/java/org/android/bbangzip/presentation/component/button/BbangZipButton.kt index ab3fa37e..03d395bf 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/component/button/BbangZipButton.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/component/button/BbangZipButton.kt @@ -83,6 +83,8 @@ fun BbangZipButton( ) }, trailingIcon = { + Spacer(modifier = Modifier.width(bbangZipButtonSize.spacing)) + if (trailingIcon != null) { Icon( imageVector = ImageVector.vectorResource(trailingIcon), @@ -90,7 +92,6 @@ fun BbangZipButton( contentDescription = null, tint = contentColor, ) - Spacer(modifier = Modifier.width(bbangZipButtonSize.spacing)) } }, ) From 495c9ec0ebd68453ae7aa4b2e8e23e8dca2ed0a0 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sat, 18 Jan 2025 00:09:15 +0900 Subject: [PATCH 13/40] =?UTF-8?q?[fix]=20#31=20Balloon=20vertical=20?= =?UTF-8?q?=EC=A1=B0=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/balloon/BalloonContainer.kt | 2 +- .../bbangzip/presentation/ui/todo/TodoRoute.kt | 5 +++++ app/src/main/res/values/strings.xml | 15 ++++++++++++--- 3 files changed, 18 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/component/balloon/BalloonContainer.kt b/app/src/main/java/org/android/bbangzip/presentation/component/balloon/BalloonContainer.kt index 70d362bb..63256b91 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/component/balloon/BalloonContainer.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/component/balloon/BalloonContainer.kt @@ -34,7 +34,7 @@ fun BalloonContainer( .padding(horizontal = 16.dp, vertical = 8.dp), contentAlignment = Alignment.Center, ) { - Row { + Row(verticalAlignment = Alignment.CenterVertically) { leadingIcon() Text( diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt index b80bc075..e1d7218b 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt @@ -7,6 +7,9 @@ import androidx.compose.runtime.getValue import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import kotlinx.coroutines.flow.collectLatest +import java.time.LocalDateTime +import java.time.format.DateTimeFormatter +import java.util.Locale @Composable fun TodoRoute( @@ -17,6 +20,7 @@ fun TodoRoute( ) { val todoState by viewModel.uiState.collectAsStateWithLifecycle() val success by viewModel.success.collectAsStateWithLifecycle(initialValue = false) + val todayDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("MM-dd-E").withLocale(Locale.forLanguageTag("ko"))).split("-") LaunchedEffect(viewModel.uiSideEffect) { viewModel.uiSideEffect.collectLatest { effect -> @@ -37,6 +41,7 @@ fun TodoRoute( true -> TodoScreen( todoState = todoState, + todayDate= todayDate, snackBarHostState = snackBarHostState, onAddPendingStudyButtonClicked = { viewModel.setEvent(TodoContract.TodoEvent.OnAddPendingStudyButtonClicked) diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index db297fcd..b1a7ea5c 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -65,11 +65,20 @@ 수강하는 과목 중 한 가지만 먼저 입력해 볼까요? >%s %s에 재학 중이시네요! + + %s/%s + recent leastVolume nearestDeadline - - - %s/%s + + + 사장님의 밀린 공부는 빵 개! + 사장님의 과제 빵점 탈출을 응원해요! + 벌써 %s나 완료 하셨네요 + 아직 완료된 할일이 없네요! + 총 %s개의 공부가 남았어요 + 오늘의 공부를 모두 끝냈어요! + 사장님 퇴근 준비 완료 \ No newline at end of file From 40b7e42c9717681c01b711f4b054de19fdbdda65 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sat, 18 Jan 2025 14:05:08 +0900 Subject: [PATCH 14/40] =?UTF-8?q?[add]=20#31=20onFetchScreenCard=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/android/bbangzip/presentation/ui/todo/TodoContract.kt | 2 ++ app/src/main/res/values/strings.xml | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt index f4220116..25067e68 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt @@ -44,6 +44,7 @@ class TodoContract { data object OnItemDeleteButtonClicked : TodoEvent + data class OnRevertCompleteBottomSheetApproveButtonClicked( val pieceId: Int, val cardState: BbangZipCardState @@ -60,6 +61,7 @@ class TodoContract { data class OnDeleteScreenCardClicked(val pieceId: Int) : TodoEvent + data class OnFetchScreenCardClicked(val pieceId: Int,val cardState: BbangZipCardState) : TodoEvent } sealed interface TodoReduce : BaseContract.Reduce { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index b1a7ea5c..3cace00b 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -76,7 +76,7 @@ 사장님의 밀린 공부는 빵 개! 사장님의 과제 빵점 탈출을 응원해요! - 벌써 %s나 완료 하셨네요 + 벌써 %s개나 완료 하셨네요 아직 완료된 할일이 없네요! 총 %s개의 공부가 남았어요 오늘의 공부를 모두 끝냈어요! From 24b4809c12b533ab1b2bbd3a0946c70f2f9c9c02 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sat, 18 Jan 2025 14:05:35 +0900 Subject: [PATCH 15/40] =?UTF-8?q?[feat]=20#31=20todoScreen=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/component/card/ToDoCard.kt | 183 ++++--- .../presentation/ui/todo/TodoScreen.kt | 507 +++++++++++++++++- 2 files changed, 596 insertions(+), 94 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt b/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt index 4d3ec63e..db4d8968 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt @@ -35,7 +35,6 @@ import org.android.bbangzip.ui.theme.BbangZipTheme fun ToDoCard( data: ToDoCardModel, modifier: Modifier = Modifier, - isDeleted: Boolean = false, onClick: () -> Unit = {}, ) { val state = data.cardState @@ -43,32 +42,32 @@ fun ToDoCard( val infoOpacity = state.getInfoOpacity() Box( modifier = - modifier - .applyShadows( - shadowType = state.getShadowOptions(), - shape = RoundedCornerShape(size = radius), - ) - .fillMaxWidth() - .border( - width = state.getBorderWidth(), - color = state.getBorderColor(), - shape = RoundedCornerShape(size = radius), - ) - .background( - color = state.getBackgroundColor(), - shape = RoundedCornerShape(size = radius), - ) - .applyFilterOnClick( - baseColor = state.getBackgroundColor(), - isDisabled = isDeleted, - radius = radius, - ) { if (!isDeleted) onClick() } - .padding(horizontal = 16.dp, vertical = 10.dp), + modifier + .applyShadows( + shadowType = state.getShadowOptions(), + shape = RoundedCornerShape(size = radius), + ) + .fillMaxWidth() + .border( + width = state.getBorderWidth(), + color = state.getBorderColor(), + shape = RoundedCornerShape(size = radius), + ) + .background( + color = state.getBackgroundColor(), + shape = RoundedCornerShape(size = radius), + ) + .applyFilterOnClick( + baseColor = state.getBackgroundColor(), + isDisabled = false, + radius = radius, + ) { onClick() } + .padding(horizontal = 16.dp, vertical = 10.dp), ) { Row( modifier = - Modifier - .fillMaxWidth(), + Modifier + .fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, ) { ToDoInfo( @@ -105,9 +104,9 @@ fun ToDoInfo( val chipBackgroundColor = if (data.remainingDays >= 0) { - getColor(BbangZipTheme.colors.labelAlternative_282119_61) - } else { getColor(BbangZipTheme.colors.statusDestructive_FF8345) + } else { + getColor(BbangZipTheme.colors.labelAlternative_282119_61) } Column(modifier = modifier) { @@ -115,11 +114,11 @@ fun ToDoInfo( if (data.subjectName.isNotBlank() && data.examName.isNotBlank()) { Text( text = - stringResource( - R.string.card_subject_exam_name_text, - data.subjectName, - data.examName, - ), + stringResource( + R.string.card_subject_exam_name_text, + data.subjectName, + data.examName, + ), style = BbangZipTheme.typography.caption2Medium, color = getColor(BbangZipTheme.colors.labelAssistive_282119_28), ) @@ -137,11 +136,11 @@ fun ToDoInfo( Text( text = - stringResource( - R.string.card_start_end_day_text, - data.startPage, - data.finishPage, - ), + stringResource( + R.string.card_start_end_day_text, + data.startPage, + data.finishPage, + ), style = BbangZipTheme.typography.label1Bold, color = getColor(BbangZipTheme.colors.labelNormal_282119), ) @@ -175,10 +174,10 @@ fun CheckSpace( Box( contentAlignment = Alignment.Center, modifier = - modifier - .background(color = backgroundColor, shape = RoundedCornerShape(12.dp)) - .height(32.dp) - .width(32.dp), + modifier + .background(color = backgroundColor, shape = RoundedCornerShape(12.dp)) + .height(32.dp) + .width(32.dp), ) { if (isCompleted) { Icon( @@ -197,71 +196,71 @@ fun ToDoCardPreview() { Column { ToDoCard( data = - ToDoCardModel( - subjectName = "경제통계학개론", - examName = "중간고사", - studyContents = "경제통계학", - startPage = 36, - finishPage = 60, - deadline = "2025년 4월 25일", - pieceId = 1, - remainingDays = 1, - cardState = BbangZipCardState.DEFAULT, - ), + ToDoCardModel( + subjectName = "경제통계학개론", + examName = "중간고사", + studyContents = "경제통계학", + startPage = 36, + finishPage = 60, + deadline = "2025년 4월 25일", + pieceId = 1, + remainingDays = 1, + cardState = BbangZipCardState.DEFAULT, + ), modifier = - Modifier - .padding(16.dp), + Modifier + .padding(16.dp), ) ToDoCard( data = - ToDoCardModel( - subjectName = "경제통계학개론", - examName = "중간고사", - studyContents = "경제통계학", - startPage = 36, - finishPage = 60, - deadline = "2025년 4월 25일", - pieceId = 1, - remainingDays = 1, - cardState = BbangZipCardState.CHECKED, - ), + ToDoCardModel( + subjectName = "경제통계학개론", + examName = "중간고사", + studyContents = "경제통계학", + startPage = 36, + finishPage = 60, + deadline = "2025년 4월 25일", + pieceId = 1, + remainingDays = 1, + cardState = BbangZipCardState.CHECKED, + ), modifier = - Modifier - .padding(16.dp), + Modifier + .padding(16.dp), ) ToDoCard( data = - ToDoCardModel( - subjectName = "", - examName = "", - studyContents = "경제통계학", - startPage = 36, - finishPage = 60, - deadline = "2025년 4월 25일", - pieceId = 1, - remainingDays = 1, - cardState = BbangZipCardState.CHECKABLE, - ), + ToDoCardModel( + subjectName = "", + examName = "", + studyContents = "경제통계학", + startPage = 36, + finishPage = 60, + deadline = "2025년 4월 25일", + pieceId = 1, + remainingDays = 1, + cardState = BbangZipCardState.CHECKABLE, + ), modifier = - Modifier - .padding(16.dp), + Modifier + .padding(16.dp), ) ToDoCard( data = - ToDoCardModel( - subjectName = "경제통계학개론", - examName = "중간고사", - studyContents = "경제통계학", - startPage = 36, - finishPage = 60, - deadline = "2025년 4월 25일", - pieceId = 1, - remainingDays = 1, - cardState = BbangZipCardState.COMPLETE, - ), + ToDoCardModel( + subjectName = "경제통계학개론", + examName = "중간고사", + studyContents = "경제통계학", + startPage = 36, + finishPage = 60, + deadline = "2025년 4월 25일", + pieceId = 1, + remainingDays = 1, + cardState = BbangZipCardState.COMPLETE, + ), modifier = - Modifier - .padding(16.dp), + Modifier + .padding(16.dp), ) } } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt index 1554e0f8..80cf0304 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt @@ -1,14 +1,51 @@ package org.android.bbangzip.presentation.ui.todo +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +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.layout.width +import androidx.compose.foundation.layout.wrapContentSize +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.Icon import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.platform.LocalConfiguration +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.tooling.preview.Preview +import androidx.compose.ui.unit.dp +import org.android.bbangzip.R +import org.android.bbangzip.presentation.component.balloon.TopTailBalloon +import org.android.bbangzip.presentation.component.button.BbangZipButton import org.android.bbangzip.presentation.component.card.BbangZipCardState +import org.android.bbangzip.presentation.component.card.ToDoCard +import org.android.bbangzip.presentation.model.card.ToDoCardModel +import org.android.bbangzip.presentation.type.BbangZipButtonSize +import org.android.bbangzip.presentation.type.BbangZipButtonType +import org.android.bbangzip.presentation.type.ToDoScreenType +import org.android.bbangzip.presentation.util.modifier.applyFilterOnClick +import org.android.bbangzip.ui.theme.BbangZipTheme @Composable fun TodoScreen( todoState: TodoContract.TodoState, + todayDate: List, snackBarHostState: SnackbarHostState, modifier: Modifier = Modifier, onAddPendingStudyButtonClicked: () -> Unit = {}, @@ -22,7 +59,473 @@ fun TodoScreen( onDeleteIconClicked: () -> Unit = {}, onCloseIconClicked: () -> Unit = {}, onItemDeleteButtonClicked: () -> Unit = {}, - onDeleteScreenCardClicked: (Int) -> Unit = {} + onDeleteScreenCardClicked: (Int) -> Unit = {}, + onFetchScreenCardClicked: (Int, BbangZipCardState) -> Unit = { _, _ -> }, ) { - Text("todo 탭") + LazyColumn( + modifier = modifier + .fillMaxSize() + .background(color = BbangZipTheme.colors.staticWhite_FFFFFF) + .padding(bottom = 64.dp) + ) { + item { + DateMessageCard( + todayDate = todayDate, + pendingCount = todoState.pendingCount, + onAddPendingStudyButtonClicked = onAddPendingStudyButtonClicked + ) + } + + item { + Spacer(Modifier.height(48.dp)) + } + + item { + StudyCountText( + remainingCount = todoState.pendingCount, + completeCount = todoState.completeCount, + modifier = modifier.padding(horizontal = 16.dp) + ) + } + + item { + Spacer(Modifier.height(16.dp)) + } + + item { + DeleteAndFilterIcons( + onDeleteIconClicked = onDeleteIconClicked, + onFilterIconClicked = onFilterIconClicked, + modifier = Modifier.padding(horizontal = 16.dp) + ) + } + + item { + Spacer(Modifier.height(18.dp)) + } + + items( + count = todoState.todoList.size, + key = { index -> + todoState.todoList[index].pieceId + }) { index -> + ToDoCard( + data = todoState.todoList[index], + modifier = Modifier.padding(horizontal = 24.dp, vertical = 6.dp), + onClick = { + when { + (todoState.screenType == ToDoScreenType.FETCH) && (todoState.todoList[index].cardState == BbangZipCardState.DEFAULT) -> + onFetchScreenCardClicked( + todoState.todoList[index].pieceId, + BbangZipCardState.COMPLETE + ) + + (todoState.screenType == ToDoScreenType.FETCH) && (todoState.todoList[index].cardState == BbangZipCardState.COMPLETE) -> + onFetchScreenCardClicked( + todoState.todoList[index].pieceId, + BbangZipCardState.DEFAULT + ) + + (todoState.screenType == ToDoScreenType.DELETE) && (todoState.todoList[index].cardState == BbangZipCardState.CHECKED) -> + onFetchScreenCardClicked( + todoState.todoList[index].pieceId, + BbangZipCardState.CHECKABLE + ) + + else -> + onFetchScreenCardClicked( + todoState.todoList[index].pieceId, + BbangZipCardState.CHECKED + ) + } + } + ) + } + } +} + +@Composable +fun DateMessageCard( + todayDate: List, + pendingCount: Int, + onAddPendingStudyButtonClicked: () -> Unit, + modifier: Modifier = Modifier +) { + Box( + modifier = modifier + .fillMaxWidth() + ) { + Column(modifier = Modifier.fillMaxWidth()) { + Column( + Modifier + .background(color = BbangZipTheme.colors.backgroundAccent_FFDAA0, shape = RoundedCornerShape(bottomEnd = 32.dp, bottomStart = 32.dp)) + .fillMaxWidth() + .height(LocalConfiguration.current.screenHeightDp.dp * (172f / 764f)) + .padding(start = 24.dp) + ) { + Spacer(modifier = Modifier.height(44.dp)) + + Row( + verticalAlignment = Alignment.CenterVertically, + modifier = Modifier.padding(start = 8.dp) + ) { + Text( + text = todayDate[0].toInt().toString(), + style = BbangZipTheme.typography.title3Bold, + color = BbangZipTheme.colors.labelNormal_282119 + ) + + Text( + text = stringResource(R.string.todo_month_text), + style = BbangZipTheme.typography.headline1Bold, + color = BbangZipTheme.colors.labelAlternative_282119_61 + ) + + Spacer(modifier = Modifier.width(8.dp)) + + Text( + text = todayDate[1].toInt().toString(), + style = BbangZipTheme.typography.title3Bold, + color = BbangZipTheme.colors.labelNormal_282119 + ) + + Text( + text = stringResource(R.string.todo_day_text), + style = BbangZipTheme.typography.headline1Bold, + color = BbangZipTheme.colors.labelAlternative_282119_61 + ) + + Spacer(modifier = Modifier.width(8.dp)) + + Text( + text = todayDate[2], + style = BbangZipTheme.typography.body1Bold, + color = BbangZipTheme.colors.labelNormal_282119 + ) + } + + Spacer(modifier = modifier.height(8.dp)) + + if (pendingCount == 0) { + Text( + text = stringResource(R.string.todo_pending_count_text), + style = BbangZipTheme.typography.headline1Bold, + color = BbangZipTheme.colors.labelAlternative_282119_61 + ) + + Spacer(modifier = Modifier.height(62.dp)) + } else { + BbangZipButton( + bbangZipButtonType = BbangZipButtonType.Outlined, + bbangZipButtonSize = BbangZipButtonSize.Medium, + onClick = { onAddPendingStudyButtonClicked() }, + label = String.format(stringResource(R.string.btn_todo_overdue_label), pendingCount), + trailingIcon = R.drawable.ic_chevronright_thick_small_24, + modifier = Modifier.wrapContentSize(), + ) + + Spacer(modifier = Modifier.height(48.dp)) + } + } + + Spacer(modifier = Modifier.height(24.dp)) + } + + TopTailBalloon( + text = stringResource(R.string.todo_top_tail_balloon_text), + leadingIcon = { + Icon( + imageVector = ImageVector.vectorResource(id = R.drawable.ic_announcement_default_24), + contentDescription = null, + tint = BbangZipTheme.colors.labelNormal_282119 + ) + + Spacer(modifier = Modifier.width(6.dp)) + }, + horizontalPadding = 16.dp, + modifier = Modifier.align(Alignment.BottomCenter) + ) + } +} + +@Composable +fun StudyCountText( + remainingCount: Int, + completeCount: Int, + modifier: Modifier = Modifier +) { + Column( + modifier = modifier + .fillMaxWidth() + .padding(start = 8.dp) + ) { + Text( + text = when { + completeCount > 0 -> stringResource(R.string.todo_complete_count_text, completeCount) + remainingCount == 0 -> stringResource(R.string.todo_complete_remaining_nothing_text) + else -> stringResource(R.string.todo_complete_nothing_text) + }, + style = BbangZipTheme.typography.label1Bold, + color = BbangZipTheme.colors.labelAlternative_282119_61 + ) + + Text( + text = if (remainingCount != 0) stringResource(R.string.todo_remaing_count_text, remainingCount) + else stringResource(R.string.todo_complete_nothing_text), + style = BbangZipTheme.typography.title3Bold, + color = BbangZipTheme.colors.labelNormal_282119 + ) + } +} + +@Composable +fun DeleteAndFilterIcons( + modifier: Modifier = Modifier, + onDeleteIconClicked: () -> Unit = {}, + onFilterIconClicked: () -> Unit = {}, +) { + Row( + modifier = modifier.fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Spacer(modifier = Modifier.weight(1f)) + + Box( + modifier = Modifier + .clip(CircleShape) + .clickable { onDeleteIconClicked() } + , contentAlignment = Alignment.Center + ) { + Icon( + imageVector = ImageVector.vectorResource(R.drawable.ic_trash_default_24), + contentDescription = null, + modifier = Modifier.padding(8.dp), + tint = BbangZipTheme.colors.labelAlternative_282119_61 + ) + } + + Box( + modifier = Modifier + .clip(CircleShape) + .clickable { onDeleteIconClicked() } + , contentAlignment = Alignment.Center + ) { + Icon( + imageVector = ImageVector.vectorResource(R.drawable.ic_filter_default_24), + contentDescription = null, + modifier = Modifier.padding(8.dp), + tint = BbangZipTheme.colors.labelAlternative_282119_61 + + ) + } + } } + +// +//@Preview(showBackground = true) +//@Composable +//private fun TodoScreenPreview() { +// Column(Modifier.fillMaxSize()) { +// DateMessageCard( +// todayDate = listOf("1", "2", "월"), +// pendingCount = 1, +// onAddPendingStudyButtonClicked = {} +// ) +// Spacer(Modifier.height(16.dp)) +// StudyCountText( +// 1, 0, +// Modifier.padding(horizontal = 16.dp) +// ) +// +// Spacer(modifier = Modifier.height(16.dp)) +// +// DeleteAndFilterIcons(Modifier.padding(horizontal = 16.dp)) +// +// Spacer(Modifier.height(24.dp)) +// +// LazyColumn { +// +// } +// } +//} + +@Preview(showBackground = true) +@Composable +fun TodoScreenMockPreview() { + val mockToDoList = listOf( + ToDoCardModel( + pieceId = 1, + subjectName = "Math", + examName = "Algebra Exam", + studyContents = "Review Chapters 1-3", + startPage = 1, + finishPage = 50, + deadline = "2025-01-20", + remainingDays = 2, + cardState = BbangZipCardState.DEFAULT + ), + ToDoCardModel( + pieceId = 2, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = 4, + cardState = BbangZipCardState.COMPLETE + ), + ToDoCardModel( + pieceId = 3, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 7, + cardState = BbangZipCardState.CHECKED + ), + ToDoCardModel( + pieceId = 4, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Complete abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = 10, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 2, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = 4, + cardState = BbangZipCardState.COMPLETE + ), + ToDoCardModel( + pieceId = 3, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 7, + cardState = BbangZipCardState.CHECKED + ), + ToDoCardModel( + pieceId = 4, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Complete abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = 10, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 2, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = 4, + cardState = BbangZipCardState.COMPLETE + ), + ToDoCardModel( + pieceId = 3, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 7, + cardState = BbangZipCardState.CHECKED + ), + ToDoCardModel( + pieceId = 4, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Complete abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = 10, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 2, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = 4, + cardState = BbangZipCardState.COMPLETE + ), + ToDoCardModel( + pieceId = 3, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 7, + cardState = BbangZipCardState.CHECKED + ), + ToDoCardModel( + pieceId = 4, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Complete abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = 10, + cardState = BbangZipCardState.CHECKABLE + ) + ) + + val mockTodoStates = listOf( + TodoContract.TodoState( + todoList = mockToDoList, + pendingCount = 2, + remainingStudyCount = 1, + completeCount = 1, + screenType = ToDoScreenType.FETCH + ), + TodoContract.TodoState( + todoList = mockToDoList, + pendingCount = 1, + remainingStudyCount = 0, + completeCount = 3, + screenType = ToDoScreenType.DELETE + ), + TodoContract.TodoState( + todoList = mockToDoList, + pendingCount = 0, + remainingStudyCount = 2, + completeCount = 2, + screenType = ToDoScreenType.EMPTY + ) + ) + + TodoScreen( + todoState = mockTodoStates[0], + todayDate = listOf("2025", "01", "18"), + snackBarHostState = SnackbarHostState() + ) + +} \ No newline at end of file From ed0565753663cb85e4e8f8c311d8aa2a9e552be4 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sat, 18 Jan 2025 14:49:07 +0900 Subject: [PATCH 16/40] =?UTF-8?q?[fix]=20#31=20ModifierExt=20->=20applyFil?= =?UTF-8?q?terOnClick=20=ED=95=A8=EC=88=98=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bbangzip/presentation/util/modifier/ModifierExt.kt | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/util/modifier/ModifierExt.kt b/app/src/main/java/org/android/bbangzip/presentation/util/modifier/ModifierExt.kt index 56c2991a..04c2d2d6 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/util/modifier/ModifierExt.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/util/modifier/ModifierExt.kt @@ -7,11 +7,14 @@ import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.collectIsPressedAsState import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material.ripple.rememberRipple +import androidx.compose.material3.ripple import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue import androidx.compose.runtime.remember import androidx.compose.ui.Modifier import androidx.compose.ui.composed +import androidx.compose.ui.draw.clip import androidx.compose.ui.draw.drawBehind import androidx.compose.ui.focus.FocusManager import androidx.compose.ui.geometry.Size @@ -43,6 +46,7 @@ fun Modifier.noRippleClickable( role = role, ) +@Composable fun Modifier.applyFilterOnClick( baseColor: Color = Color.Transparent, radius: Dp = 0.dp, @@ -58,11 +62,14 @@ fun Modifier.applyFilterOnClick( val interactionSource = remember { MutableInteractionSource() } val isPressed by interactionSource.collectIsPressedAsState() + val rippleIndication = ripple(bounded = true) + this + .clip(RoundedCornerShape(size = radius)) .background(if (isPressed && !isDisabled) finalFilteredColor else baseColor, shape = RoundedCornerShape(size = radius)) .clickable( interactionSource = interactionSource, - indication = null, + indication = rippleIndication, onClick = { onClick() }, ) } From d4072d1308e327842759a0117d01ed9ec00df4d8 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sat, 18 Jan 2025 21:07:19 +0900 Subject: [PATCH 17/40] =?UTF-8?q?[hotfix]=20#31=20=ED=95=98=EC=A7=80?= =?UTF-8?q?=EC=9D=80=EC=9D=98=20=EA=B0=9C=ED=81=B0=20=EC=8B=A4=EC=88=98=20?= =?UTF-8?q?=EB=B0=94=EB=A1=9C=EC=9E=A1=EA=B8=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/bbangzip/presentation/util/base/BaseViewModel.kt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/util/base/BaseViewModel.kt b/app/src/main/java/org/android/bbangzip/presentation/util/base/BaseViewModel.kt index 1a9d7893..d545f6aa 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/util/base/BaseViewModel.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/util/base/BaseViewModel.kt @@ -4,6 +4,7 @@ import android.os.Parcelable import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope +import androidx.lifecycle.viewmodel.compose.viewModel import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job @@ -93,7 +94,7 @@ abstract class BaseViewModel savedStateHandle[STATE_KEY] = state.toParcelable() } - } + }.launchIn(viewModelScope) } protected fun updateState( From 4f8a56c735af1cd0db2a2c8a4e50c0e18d4a1148 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sat, 18 Jan 2025 22:48:08 +0900 Subject: [PATCH 18/40] =?UTF-8?q?[add]=20#31=20screenType=20=EB=84=A4?= =?UTF-8?q?=EC=9D=B4=EB=B0=8D=20=EB=B3=80=EA=B2=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/android/bbangzip/presentation/type/ToDoScreenType.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/type/ToDoScreenType.kt b/app/src/main/java/org/android/bbangzip/presentation/type/ToDoScreenType.kt index d6274b64..4c36f293 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/type/ToDoScreenType.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/type/ToDoScreenType.kt @@ -2,6 +2,6 @@ package org.android.bbangzip.presentation.type enum class ToDoScreenType { EMPTY, - FETCH, + DEFAULT, DELETE } \ No newline at end of file From 1ee48a6c6a59bb16a27248bde00c7fb38c65c865 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sat, 18 Jan 2025 22:48:36 +0900 Subject: [PATCH 19/40] =?UTF-8?q?[add]=20#31=20Event=20,=20Reduce=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EC=B6=94=EA=B0=80?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/ui/todo/TodoViewModel.kt | 119 +++++++++++++++--- 1 file changed, 100 insertions(+), 19 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt index 8ee6b5e9..5f5f66b5 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt @@ -3,8 +3,11 @@ package org.android.bbangzip.presentation.ui.todo import android.os.Parcelable import androidx.lifecycle.SavedStateHandle import dagger.hilt.android.lifecycle.HiltViewModel +import org.android.bbangzip.presentation.component.card.BbangZipCardState +import org.android.bbangzip.presentation.type.ToDoFilterType import org.android.bbangzip.presentation.type.ToDoScreenType import org.android.bbangzip.presentation.util.base.BaseViewModel +import timber.log.Timber import javax.inject.Inject @HiltViewModel @@ -15,7 +18,9 @@ constructor( ) : BaseViewModel( savedStateHandle = savedStateHandle, ) { - override fun createInitialState(savedState: Parcelable?): TodoContract.TodoState = TodoContract.TodoState() + override fun createInitialState(savedState: Parcelable?): TodoContract.TodoState { + return savedState as? TodoContract.TodoState ?: TodoContract.TodoState() + } init { setEvent(TodoContract.TodoEvent.Initialize) @@ -36,30 +41,96 @@ constructor( TodoContract.TodoEvent.Initialize -> launch { initDataLoad() } //Filter BottomSheet - is TodoContract.TodoEvent.OnFilterBottomSheetItemClicked -> updateState( - TodoContract.TodoReduce.UpdateFilterItemIndex(itemIndex = event.todoFilterItemIndex) - ) + is TodoContract.TodoEvent.OnFilterBottomSheetItemClicked -> { + updateState(TodoContract.TodoReduce.UpdateFilterItemIndex(itemIndex = event.todoFilterItemIndex)) + setSideEffect(TodoContract.TodoSideEffect.ShowSnackBar("${ToDoFilterType.entries[event.todoFilterItemIndex].id}으로 정렬했어요")) + //TODO index를 이용해 서버로 FetchInfo 이름 보내주기 + } TodoContract.TodoEvent.OnFilterBottomSheetDismissRequest -> updateState(TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState(todoFilterBottomSheetState = false)) - TodoContract.TodoEvent.OnFilterIconClicked -> updateState(TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState(todoFilterBottomSheetState = true)) + TodoContract.TodoEvent.OnFilterIconClicked -> { + updateState(TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState(todoFilterBottomSheetState = true)) + + } //revertComplete BottomSheet is TodoContract.TodoEvent.OnRevertCompleteBottomSheetApproveButtonClicked -> { - updateState(TodoContract.TodoReduce.UpdateCardState(pieceId = event.pieceId, cardState = event.cardState)) + updateState(TodoContract.TodoReduce.UpdateCardState(pieceId = event.pieceId, cardState = BbangZipCardState.DEFAULT)) updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = false)) + updateState(TodoContract.TodoReduce.UpdateToDoCount(completeCount = currentUiState.completeCount - 1, remainingStudyCount = currentUiState.remainingStudyCount + 1)) + setSideEffect(TodoContract.TodoSideEffect.ShowSnackBar("미완료 상태로 되돌려졌어요!")) + //TODO pieceId 사영헤사 서버로 쏘기 미완료 APT } TodoContract.TodoEvent.OnRevertCompleteBottomSheetDismissButtonClicked -> updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = false)) TodoContract.TodoEvent.OnRevertCompleteBottomSheetDismissRequest -> updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = false)) //Delete - is TodoContract.TodoEvent.OnDeleteScreenCardClicked -> - updateState(TodoContract.TodoReduce.UpdateSelectedItemList(pieceId = event.pieceId)) + is TodoContract.TodoEvent.OnDeleteScreenCardClicked -> { + when (event.cardState) { + BbangZipCardState.CHECKED -> { + updateState(TodoContract.TodoReduce.UpdateSelectedItemList(pieceId = event.pieceId)) + updateState(TodoContract.TodoReduce.UpdateCardState(pieceId = event.pieceId, cardState = event.cardState)) + } + + BbangZipCardState.CHECKABLE -> { + updateState(TodoContract.TodoReduce.DeleteSelectedItemList(pieceId = event.pieceId)) + updateState(TodoContract.TodoReduce.UpdateCardState(pieceId = event.pieceId, cardState = event.cardState)) + } + + else -> { + setSideEffect(TodoContract.TodoSideEffect.ShowSnackBar("이미 완료한 일은 삭제할 수 없어요!")) + } + } + } + //Default + is TodoContract.TodoEvent.OnDefaultScreenCardClicked -> { + if (event.cardState == BbangZipCardState.COMPLETE) { + updateState(TodoContract.TodoReduce.UpdateCardState(pieceId = event.pieceId, cardState = event.cardState)) + updateState(TodoContract.TodoReduce.UpdateToDoCount(completeCount = currentUiState.completeCount + 1, remainingStudyCount = currentUiState.remainingStudyCount - 1)) + TodoContract.TodoSideEffect.ShowSnackBar("공부완료 ! 오늘의 빵굽기 성공!") + } else { + updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = true)) + } + // TODO 서버로 pieceId 이용해서 완료 API 쏘기 + } +//통과!! + TodoContract.TodoEvent.OnDeleteIconClicked -> { + updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.DELETE)) + updateState( + TodoContract.TodoReduce.UpdateToDoListCardState( + previousCardState = BbangZipCardState.DEFAULT, + nextCardState = BbangZipCardState.CHECKABLE + ) + ) + } + TodoContract.TodoEvent.OnItemDeleteButtonClicked -> { + //TODO setlectedItemlist 사용해서 서버로 삭제한 card API 전송 + updateState( + TodoContract.TodoReduce.UpdateToDoCount( + completeCount = currentUiState.completeCount, + remainingStudyCount = currentUiState.remainingStudyCount - currentUiState.selectedItemList.size + ) + ) + if (currentUiState.remainingStudyCount != 0) { + updateState(TodoContract.TodoReduce.DeleteToDoListItems) + updateState(TodoContract.TodoReduce.UpdateToDoListCardState(previousCardState = BbangZipCardState.CHECKABLE, nextCardState = BbangZipCardState.DEFAULT)) + updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.DEFAULT)) - TodoContract.TodoEvent.OnDeleteIconClicked -> updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.DELETE)) - TodoContract.TodoEvent.OnItemDeleteButtonClicked -> updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = true)) - TodoContract.TodoEvent.OnCloseIconClicked -> updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.FETCH)) + } else { + updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.EMPTY)) + } + updateState(TodoContract.TodoReduce.ResetSelectedItemList) + setSideEffect(TodoContract.TodoSideEffect.ShowSnackBar("오늘 할 공부를 삭제했어요")) + } +// 통과 + TodoContract.TodoEvent.OnCloseIconClicked -> { + updateState(TodoContract.TodoReduce.UpdateToDoListCardState(previousCardState = BbangZipCardState.CHECKABLE, nextCardState = BbangZipCardState.DEFAULT)) + updateState(TodoContract.TodoReduce.UpdateToDoListCardState(previousCardState = BbangZipCardState.CHECKED, nextCardState = BbangZipCardState.DEFAULT)) + updateState(TodoContract.TodoReduce.ResetSelectedItemList) + updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.DEFAULT)) + } //화면 이동 TodoContract.TodoEvent.OnAddStudyButtonClicked -> setSideEffect(TodoContract.TodoSideEffect.NavigateToAddToDo) @@ -84,14 +155,16 @@ constructor( } ) - is TodoContract.TodoReduce.UpdateToDoListState -> state.copy( + is TodoContract.TodoReduce.UpdateToDoListCardState -> state.copy( // 해당 카드스태이트를 찾아서 바꿔줌 todoList = state.todoList.map { item -> - item.copy(cardState = reduce.cardState) + if (item.cardState == reduce.previousCardState) { + item.copy(cardState = reduce.nextCardState) + } else item } ) is TodoContract.TodoReduce.DeleteToDoListItems -> { - val pieceIdSet = reduce.pieceIds.toSet() + val pieceIdSet = currentUiState.selectedItemList.toSet() state.copy( todoList = state.todoList.filter { item -> item.pieceId !in pieceIdSet @@ -108,6 +181,10 @@ constructor( selectedItemList = state.selectedItemList.plus(reduce.pieceId) ) + is TodoContract.TodoReduce.DeleteSelectedItemList -> state.copy( + selectedItemList = state.selectedItemList.minus(reduce.pieceId) + ) + //Filter BottomSheet is TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState -> state.copy( todoFilterBottomSheetState = !state.todoFilterBottomSheetState @@ -118,9 +195,11 @@ constructor( ) //ToDoCount - is TodoContract.TodoReduce.UpdateToDoCount -> state.copy( - completeCount = reduce.completeCount, remainingStudyCount = reduce.remainingStudyCount - ) + is TodoContract.TodoReduce.UpdateToDoCount -> { + state.copy( + completeCount = reduce.completeCount, remainingStudyCount = reduce.remainingStudyCount + ) + } is TodoContract.TodoReduce.UpdatePendingToDoCount -> state.copy( pendingCount = reduce.pendingCount @@ -131,11 +210,13 @@ constructor( screenType = reduce.screenType ) - + TodoContract.TodoReduce.ResetSelectedItemList -> state.copy( + selectedItemList = listOf() + ) } } - private suspend fun initDataLoad() { + private fun initDataLoad() { } From 33ad706bdc2113e51831311c26d3753bec1786df Mon Sep 17 00:00:00 2001 From: beom84 Date: Sat, 18 Jan 2025 22:49:27 +0900 Subject: [PATCH 20/40] =?UTF-8?q?[feat]=20#31=20Route=20,=20Screen=20?= =?UTF-8?q?=ED=95=A8=EC=88=98=20=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/ui/todo/TodoContract.kt | 143 ++++++++- .../presentation/ui/todo/TodoRoute.kt | 28 +- .../presentation/ui/todo/TodoScreen.kt | 283 +++++++++++------- app/src/main/res/values/strings.xml | 4 +- 4 files changed, 321 insertions(+), 137 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt index 25067e68..4670d1d9 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt @@ -10,15 +10,125 @@ import org.android.bbangzip.presentation.util.base.BaseContract class TodoContract { @Parcelize data class TodoState( - val todoList: List = listOf(), - val pendingCount: Int = 0, - val remainingStudyCount: Int = 0, - val completeCount: Int = 0, + val todoList: List = listOf( + ToDoCardModel( + pieceId = 1, + subjectName = "Math", + examName = "Algebra Exam", + studyContents = "Review Chapters 1-3", + startPage = 1, + finishPage = 50, + deadline = "2025-01-20", + remainingDays = 2, + cardState = BbangZipCardState.DEFAULT + ), + ToDoCardModel( + pieceId = 2, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = -3, + cardState = BbangZipCardState.COMPLETE + ), + ToDoCardModel( + pieceId = 3, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 7, + cardState = BbangZipCardState.DEFAULT + ), + ToDoCardModel( + pieceId = 4, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Complete abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = -2, + cardState = BbangZipCardState.COMPLETE + ), + ToDoCardModel( + pieceId = 5, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = 4, + cardState = BbangZipCardState.DEFAULT + ), + ToDoCardModel( + pieceId = 6, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = -1, + cardState = BbangZipCardState.COMPLETE + ), + ToDoCardModel( + pieceId = 7, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Complete abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = 5, + cardState = BbangZipCardState.DEFAULT + ), + ToDoCardModel( + pieceId = 8, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = -4, + cardState = BbangZipCardState.COMPLETE + ), + ToDoCardModel( + pieceId = 9, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 3, + cardState = BbangZipCardState.DEFAULT + ), + ToDoCardModel( + pieceId = 10, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Complete abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = -5, + cardState = BbangZipCardState.COMPLETE + )), + val pendingCount: Int = 10, + val remainingStudyCount: Int = 5, + val completeCount: Int = 5, val todoFilterBottomSheetState: Boolean = false, val todoFilterItemIndex: Int = 0, val selectedItemList: List = listOf(), val revertCompleteBottomSheetState: Boolean = false, - val screenType: ToDoScreenType = ToDoScreenType.EMPTY + val screenType: ToDoScreenType = ToDoScreenType.DEFAULT ) : BaseContract.State, Parcelable { override fun toParcelable(): Parcelable = this } @@ -47,7 +157,6 @@ class TodoContract { data class OnRevertCompleteBottomSheetApproveButtonClicked( val pieceId: Int, - val cardState: BbangZipCardState ) : TodoEvent data class FetchToDoInfo( @@ -59,9 +168,12 @@ class TodoContract { data class OnFilterBottomSheetItemClicked(val todoFilterItemIndex: Int) : TodoEvent - data class OnDeleteScreenCardClicked(val pieceId: Int) : TodoEvent + data class OnDeleteScreenCardClicked(val pieceId: Int,val cardState: BbangZipCardState) : TodoEvent - data class OnFetchScreenCardClicked(val pieceId: Int,val cardState: BbangZipCardState) : TodoEvent + data class OnDefaultScreenCardClicked( + val pieceId: Int, + val cardState: BbangZipCardState, + ) : TodoEvent } sealed interface TodoReduce : BaseContract.Reduce { @@ -71,6 +183,7 @@ class TodoContract { val remainingStudyCount: Int, val completeCount: Int, ) : TodoReduce + data object DeleteToDoListItems : TodoReduce data class UpdateToDoFilterBottomSheetState(val todoFilterBottomSheetState: Boolean) : TodoReduce @@ -86,23 +199,25 @@ class TodoContract { val cardState: BbangZipCardState ) : TodoReduce - data class UpdateToDoListState( - val cardState: BbangZipCardState + data class UpdateToDoListCardState( + val previousCardState: BbangZipCardState, + val nextCardState: BbangZipCardState + ) : TodoReduce data class UpdateFilterItemIndex( val itemIndex: Int ) : TodoReduce - data class DeleteToDoListItems( - val pieceIds: List - ) : TodoReduce - data class UpdatePendingToDoCount(val pendingCount: Int) : TodoReduce data class UpdateScreenType(val screenType: ToDoScreenType) : TodoReduce data class UpdateSelectedItemList(val pieceId: Int) : TodoReduce + + data class DeleteSelectedItemList(val pieceId: Int) : TodoReduce + + data object ResetSelectedItemList : TodoReduce } sealed interface TodoSideEffect : BaseContract.SideEffect { diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt index e1d7218b..dac4895c 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt @@ -1,6 +1,7 @@ package org.android.bbangzip.presentation.ui.todo import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue @@ -19,8 +20,8 @@ fun TodoRoute( viewModel: TodoViewModel = hiltViewModel() ) { val todoState by viewModel.uiState.collectAsStateWithLifecycle() - val success by viewModel.success.collectAsStateWithLifecycle(initialValue = false) - val todayDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("MM-dd-E").withLocale(Locale.forLanguageTag("ko"))).split("-") + val success by viewModel.success.collectAsStateWithLifecycle(initialValue = true) + val todayDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("MM-dd-E").withLocale(Locale.forLanguageTag("ko"))).split("-") LaunchedEffect(viewModel.uiSideEffect) { viewModel.uiSideEffect.collectLatest { effect -> @@ -41,7 +42,7 @@ fun TodoRoute( true -> TodoScreen( todoState = todoState, - todayDate= todayDate, + todayDate = todayDate, snackBarHostState = snackBarHostState, onAddPendingStudyButtonClicked = { viewModel.setEvent(TodoContract.TodoEvent.OnAddPendingStudyButtonClicked) @@ -52,9 +53,9 @@ fun TodoRoute( onRevertCompleteBottomSheetDismissButtonClicked = { viewModel.setEvent(TodoContract.TodoEvent.OnRevertCompleteBottomSheetDismissButtonClicked) }, - onRevertCompleteBottomSheetApproveButtonClicked = { pieceId, cardState -> + onRevertCompleteBottomSheetApproveButtonClicked = { pieceId -> viewModel.setEvent( - TodoContract.TodoEvent.OnRevertCompleteBottomSheetApproveButtonClicked(pieceId = pieceId, cardState = cardState) + TodoContract.TodoEvent.OnRevertCompleteBottomSheetApproveButtonClicked(pieceId = pieceId) ) }, onRevertCompleteBottomSheetDismissRequest = { @@ -66,24 +67,27 @@ fun TodoRoute( onFilterBottomSheetItemClicked = { filterIndex -> viewModel.setEvent(TodoContract.TodoEvent.OnFilterBottomSheetItemClicked(todoFilterItemIndex = filterIndex)) }, - onFilterBottomSheetDismissRequest ={ + onFilterBottomSheetDismissRequest = { viewModel.setEvent(TodoContract.TodoEvent.OnFilterBottomSheetDismissRequest) }, - onDeleteIconClicked ={ + onDeleteIconClicked = { viewModel.setEvent(TodoContract.TodoEvent.OnDeleteIconClicked) }, onCloseIconClicked = { viewModel.setEvent(TodoContract.TodoEvent.OnCloseIconClicked) }, - onItemDeleteButtonClicked ={ + onItemDeleteButtonClicked = { viewModel.setEvent(TodoContract.TodoEvent.OnItemDeleteButtonClicked) }, - onDeleteScreenCardClicked = { pieceId -> - viewModel.setEvent(TodoContract.TodoEvent.OnDeleteScreenCardClicked(pieceId = pieceId)) + onDeleteScreenCardClicked = { pieceId, cardState -> + viewModel.setEvent(TodoContract.TodoEvent.OnDeleteScreenCardClicked(pieceId = pieceId, cardState = cardState)) + }, + onDefaultScreenCardClicked = { pieceId, cardState -> + viewModel.setEvent(TodoContract.TodoEvent.OnDefaultScreenCardClicked(pieceId = pieceId, cardState = cardState)) }, ) - false -> - null + false -> Text("땡!") + } } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt index 80cf0304..fdfe5ac3 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt @@ -10,7 +10,6 @@ import androidx.compose.foundation.layout.fillMaxSize import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.height import androidx.compose.foundation.layout.padding -import androidx.compose.foundation.layout.size import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.lazy.LazyColumn @@ -18,7 +17,6 @@ import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape import androidx.compose.material3.Icon import androidx.compose.material3.SnackbarHostState -import androidx.compose.material3.Surface import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -35,11 +33,11 @@ import org.android.bbangzip.presentation.component.balloon.TopTailBalloon import org.android.bbangzip.presentation.component.button.BbangZipButton import org.android.bbangzip.presentation.component.card.BbangZipCardState import org.android.bbangzip.presentation.component.card.ToDoCard +import org.android.bbangzip.presentation.component.snackbar.BbangZipSnackBarHost import org.android.bbangzip.presentation.model.card.ToDoCardModel import org.android.bbangzip.presentation.type.BbangZipButtonSize import org.android.bbangzip.presentation.type.BbangZipButtonType import org.android.bbangzip.presentation.type.ToDoScreenType -import org.android.bbangzip.presentation.util.modifier.applyFilterOnClick import org.android.bbangzip.ui.theme.BbangZipTheme @Composable @@ -51,7 +49,7 @@ fun TodoScreen( onAddPendingStudyButtonClicked: () -> Unit = {}, onAddStudyButtonClicked: () -> Unit = {}, onRevertCompleteBottomSheetDismissButtonClicked: () -> Unit = {}, - onRevertCompleteBottomSheetApproveButtonClicked: (Int, BbangZipCardState) -> Unit = { _, _ -> }, + onRevertCompleteBottomSheetApproveButtonClicked: (Int) -> Unit = {}, onRevertCompleteBottomSheetDismissRequest: () -> Unit = {}, onFilterIconClicked: () -> Unit = {}, onFilterBottomSheetItemClicked: (Int) -> Unit = {}, @@ -59,91 +57,156 @@ fun TodoScreen( onDeleteIconClicked: () -> Unit = {}, onCloseIconClicked: () -> Unit = {}, onItemDeleteButtonClicked: () -> Unit = {}, - onDeleteScreenCardClicked: (Int) -> Unit = {}, - onFetchScreenCardClicked: (Int, BbangZipCardState) -> Unit = { _, _ -> }, + onDeleteScreenCardClicked: (Int, BbangZipCardState) -> Unit = { _, _ -> }, + onDefaultScreenCardClicked: (Int, BbangZipCardState) -> Unit = { _, _ -> }, ) { - LazyColumn( - modifier = modifier - .fillMaxSize() - .background(color = BbangZipTheme.colors.staticWhite_FFFFFF) - .padding(bottom = 64.dp) - ) { - item { - DateMessageCard( - todayDate = todayDate, - pendingCount = todoState.pendingCount, - onAddPendingStudyButtonClicked = onAddPendingStudyButtonClicked - ) - } - - item { - Spacer(Modifier.height(48.dp)) - } + Box(modifier = Modifier.fillMaxSize()) { + LazyColumn( + modifier = modifier + .fillMaxSize() + .background(color = BbangZipTheme.colors.staticWhite_FFFFFF) + .padding(bottom = 74.dp) + ) { + item { + DateMessageCard( + todayDate = todayDate, + pendingCount = todoState.pendingCount, + onAddPendingStudyButtonClicked = onAddPendingStudyButtonClicked + ) - item { - StudyCountText( - remainingCount = todoState.pendingCount, - completeCount = todoState.completeCount, - modifier = modifier.padding(horizontal = 16.dp) - ) - } + Spacer(Modifier.height(48.dp)) + } - item { - Spacer(Modifier.height(16.dp)) - } + if (todoState.screenType == ToDoScreenType.EMPTY) { + item { + EmptyView(onAddStudyButtonClicked = onAddStudyButtonClicked) + } + } - item { - DeleteAndFilterIcons( - onDeleteIconClicked = onDeleteIconClicked, - onFilterIconClicked = onFilterIconClicked, - modifier = Modifier.padding(horizontal = 16.dp) - ) - } + if (todoState.screenType == ToDoScreenType.DEFAULT) { + item { + StudyCountText( + remainingCount = todoState.remainingStudyCount, + completeCount = todoState.completeCount, + ) - item { - Spacer(Modifier.height(18.dp)) - } + Spacer(Modifier.height(16.dp)) - items( - count = todoState.todoList.size, - key = { index -> - todoState.todoList[index].pieceId - }) { index -> - ToDoCard( - data = todoState.todoList[index], - modifier = Modifier.padding(horizontal = 24.dp, vertical = 6.dp), - onClick = { - when { - (todoState.screenType == ToDoScreenType.FETCH) && (todoState.todoList[index].cardState == BbangZipCardState.DEFAULT) -> - onFetchScreenCardClicked( - todoState.todoList[index].pieceId, - BbangZipCardState.COMPLETE - ) + DeleteAndFilterIcons( + onDeleteIconClicked = onDeleteIconClicked, + onFilterIconClicked = onFilterIconClicked, + ) - (todoState.screenType == ToDoScreenType.FETCH) && (todoState.todoList[index].cardState == BbangZipCardState.COMPLETE) -> - onFetchScreenCardClicked( - todoState.todoList[index].pieceId, - BbangZipCardState.DEFAULT - ) + Spacer(Modifier.height(10.dp)) + } + } - (todoState.screenType == ToDoScreenType.DELETE) && (todoState.todoList[index].cardState == BbangZipCardState.CHECKED) -> - onFetchScreenCardClicked( - todoState.todoList[index].pieceId, - BbangZipCardState.CHECKABLE - ) + if (todoState.screenType == ToDoScreenType.DELETE) { + item { + Text( + text = stringResource(R.string.todo_delete_screen_text), + style = BbangZipTheme.typography.heading2Bold, + color = BbangZipTheme.colors.labelNormal_282119, + modifier = Modifier.padding(start = 24.dp) + ) - else -> - onFetchScreenCardClicked( - todoState.todoList[index].pieceId, - BbangZipCardState.CHECKED + Spacer(Modifier.height(4.dp)) + + Row( + modifier = Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically + ) { + Spacer(modifier = Modifier.weight(1f)) + + Box( + modifier = Modifier + .clip(CircleShape) + .clickable { onCloseIconClicked() }, contentAlignment = Alignment.Center + ) { + Icon( + imageVector = ImageVector.vectorResource(R.drawable.ic_x_small_24), + contentDescription = null, + modifier = Modifier.padding(8.dp), + tint = BbangZipTheme.colors.labelAlternative_282119_61 ) + } } + Spacer(Modifier.height(10.dp)) } - ) + } + + if (todoState.screenType != ToDoScreenType.EMPTY) { + items( + count = todoState.todoList.size, + key = { index -> + todoState.todoList[index].pieceId + }) { index -> + ToDoCard( + data = todoState.todoList[index], + modifier = Modifier.padding(horizontal = 16.dp, vertical = 6.dp), + onClick = { + when { + (todoState.screenType == ToDoScreenType.DEFAULT) && (todoState.todoList[index].cardState == BbangZipCardState.DEFAULT) -> + onDefaultScreenCardClicked( + todoState.todoList[index].pieceId, + BbangZipCardState.COMPLETE + ) + + (todoState.screenType == ToDoScreenType.DEFAULT) && (todoState.todoList[index].cardState == BbangZipCardState.COMPLETE) -> + onDefaultScreenCardClicked( + todoState.todoList[index].pieceId, + BbangZipCardState.DEFAULT + ) + + (todoState.screenType == ToDoScreenType.DELETE) && (todoState.todoList[index].cardState == BbangZipCardState.CHECKED) -> + onDeleteScreenCardClicked( + todoState.todoList[index].pieceId, + BbangZipCardState.CHECKABLE + ) + + (todoState.screenType == ToDoScreenType.DELETE) && (todoState.todoList[index].cardState == BbangZipCardState.CHECKABLE) -> + onDeleteScreenCardClicked( + todoState.todoList[index].pieceId, + BbangZipCardState.CHECKED + ) + + else -> + onDeleteScreenCardClicked( + todoState.todoList[index].pieceId, + BbangZipCardState.COMPLETE + ) + } + } + ) + } + } + if (todoState.screenType == ToDoScreenType.DELETE) { + item { + Spacer(modifier = Modifier.height(10.dp)) + + BbangZipButton( + bbangZipButtonType = BbangZipButtonType.Solid, + bbangZipButtonSize = BbangZipButtonSize.Large, + onClick = { onItemDeleteButtonClicked() }, + label = stringResource(R.string.todo_delete_screen_delete_button_text, todoState.selectedItemList.size), + modifier = Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), + isEnable = todoState.selectedItemList.isNotEmpty(), + trailingIcon = R.drawable.ic_plus_thick_24, + ) + + Spacer(modifier = Modifier.height(16.dp)) + + } + } } } } + @Composable fun DateMessageCard( todayDate: List, @@ -256,12 +319,13 @@ fun StudyCountText( ) { Column( modifier = modifier + .padding(horizontal = 16.dp) .fillMaxWidth() .padding(start = 8.dp) ) { Text( text = when { - completeCount > 0 -> stringResource(R.string.todo_complete_count_text, completeCount) + completeCount > 0 && remainingCount != 0-> stringResource(R.string.todo_complete_count_text, completeCount) remainingCount == 0 -> stringResource(R.string.todo_complete_remaining_nothing_text) else -> stringResource(R.string.todo_complete_nothing_text) }, @@ -271,7 +335,7 @@ fun StudyCountText( Text( text = if (remainingCount != 0) stringResource(R.string.todo_remaing_count_text, remainingCount) - else stringResource(R.string.todo_complete_nothing_text), + else stringResource(R.string.todo_remaining_nothing_text), style = BbangZipTheme.typography.title3Bold, color = BbangZipTheme.colors.labelNormal_282119 ) @@ -285,7 +349,9 @@ fun DeleteAndFilterIcons( onFilterIconClicked: () -> Unit = {}, ) { Row( - modifier = modifier.fillMaxWidth(), + modifier = modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), verticalAlignment = Alignment.CenterVertically ) { Spacer(modifier = Modifier.weight(1f)) @@ -293,9 +359,8 @@ fun DeleteAndFilterIcons( Box( modifier = Modifier .clip(CircleShape) - .clickable { onDeleteIconClicked() } - , contentAlignment = Alignment.Center - ) { + .clickable { onDeleteIconClicked() }, contentAlignment = Alignment.Center + ) { Icon( imageVector = ImageVector.vectorResource(R.drawable.ic_trash_default_24), contentDescription = null, @@ -307,8 +372,7 @@ fun DeleteAndFilterIcons( Box( modifier = Modifier .clip(CircleShape) - .clickable { onDeleteIconClicked() } - , contentAlignment = Alignment.Center + .clickable { onFilterIconClicked() }, contentAlignment = Alignment.Center ) { Icon( imageVector = ImageVector.vectorResource(R.drawable.ic_filter_default_24), @@ -321,33 +385,33 @@ fun DeleteAndFilterIcons( } } -// -//@Preview(showBackground = true) -//@Composable -//private fun TodoScreenPreview() { -// Column(Modifier.fillMaxSize()) { -// DateMessageCard( -// todayDate = listOf("1", "2", "월"), -// pendingCount = 1, -// onAddPendingStudyButtonClicked = {} -// ) -// Spacer(Modifier.height(16.dp)) -// StudyCountText( -// 1, 0, -// Modifier.padding(horizontal = 16.dp) -// ) -// -// Spacer(modifier = Modifier.height(16.dp)) -// -// DeleteAndFilterIcons(Modifier.padding(horizontal = 16.dp)) -// -// Spacer(Modifier.height(24.dp)) -// -// LazyColumn { -// -// } -// } -//} +@Composable +fun EmptyView( + modifier: Modifier = Modifier, + onAddStudyButtonClicked: () -> Unit = {} +) { + Column(modifier = modifier.padding(horizontal = 16.dp)) { + Box( + modifier = Modifier + .fillMaxWidth() + .height(328.dp) + .background(color = BbangZipTheme.colors.backgroundAlternative_F5F5F5, shape = RoundedCornerShape(size = 32.dp)), contentAlignment = Alignment.Center + ) { + Text(text = "Empty View") + } + + Spacer(modifier = Modifier.height(16.dp)) + + BbangZipButton( + bbangZipButtonType = BbangZipButtonType.Solid, + bbangZipButtonSize = BbangZipButtonSize.Large, + onClick = { onAddStudyButtonClicked() }, + label = stringResource(R.string.btn_add_todo_label), + modifier = Modifier.fillMaxWidth(), + trailingIcon = R.drawable.ic_plus_thick_24, + ) + } +} @Preview(showBackground = true) @Composable @@ -504,7 +568,7 @@ fun TodoScreenMockPreview() { pendingCount = 2, remainingStudyCount = 1, completeCount = 1, - screenType = ToDoScreenType.FETCH + screenType = ToDoScreenType.DEFAULT ), TodoContract.TodoState( todoList = mockToDoList, @@ -527,5 +591,4 @@ fun TodoScreenMockPreview() { todayDate = listOf("2025", "01", "18"), snackBarHostState = SnackbarHostState() ) - } \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 3cace00b..bd7af5f3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -21,7 +21,7 @@ %sp - %sp %s / %s D+ - D- + D 카카오로 로그인하기 @@ -81,4 +81,6 @@ 총 %s개의 공부가 남았어요 오늘의 공부를 모두 끝냈어요! 사장님 퇴근 준비 완료 + 삭제할 오늘의 공부를 \n선택해 주세요 + %s개 삭제하기 \ No newline at end of file From f81efe9ca15856f25f301b70ae6b95d248b9f367 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sun, 19 Jan 2025 04:13:52 +0900 Subject: [PATCH 21/40] =?UTF-8?q?[fix]=20#31=20modifierEXt=20applyFilterCl?= =?UTF-8?q?ick=20=ED=95=A8=EC=88=98=20isDisable=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../android/bbangzip/presentation/util/modifier/ModifierExt.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/util/modifier/ModifierExt.kt b/app/src/main/java/org/android/bbangzip/presentation/util/modifier/ModifierExt.kt index 3adb9514..3842e19e 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/util/modifier/ModifierExt.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/util/modifier/ModifierExt.kt @@ -74,7 +74,7 @@ fun Modifier.applyFilterOnClick( .background(if (isPressed && !isDisabled) finalFilteredColor else baseColor, shape = RoundedCornerShape(size = radius)) .clickable( interactionSource = interactionSource, - indication = rippleIndication, + indication = if(!isDisabled)rippleIndication else null, onClick = { onClick() }, ) } From 5da920e93ef05997697c96ff9d939285fda23c90 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sun, 19 Jan 2025 04:14:23 +0900 Subject: [PATCH 22/40] =?UTF-8?q?[feat]=20#31=20bottomSheet=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/type/ToDoFilterType.kt | 8 +- .../presentation/ui/todo/TodoContract.kt | 10 +- .../presentation/ui/todo/TodoRoute.kt | 20 +- .../presentation/ui/todo/TodoScreen.kt | 177 ++++++++++++++---- .../presentation/ui/todo/TodoViewModel.kt | 137 +++++++++++--- app/src/main/res/values/strings.xml | 9 +- 6 files changed, 285 insertions(+), 76 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/type/ToDoFilterType.kt b/app/src/main/java/org/android/bbangzip/presentation/type/ToDoFilterType.kt index ff197792..72901b60 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/type/ToDoFilterType.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/type/ToDoFilterType.kt @@ -4,19 +4,19 @@ import androidx.annotation.StringRes import org.android.bbangzip.R enum class ToDoFilterType( - @StringRes val filter: Int, + val filter: String, val id: String, ) { RECENT( - filter = R.string.todo_filter_recent, + filter = "최근 등록 순", id = "recent", ), VOLUME( - filter = R.string.todo_filter_least_volume, + filter = "분량 적은 순", id = "leastVolume", ), DEADLINE( - filter = R.string.todo_filter_deadline, + filter = "마감 기한 빠른 순", id = "nearestDeadline", ), } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt index 4670d1d9..2949a5e1 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt @@ -4,6 +4,7 @@ import android.os.Parcelable import kotlinx.parcelize.Parcelize import org.android.bbangzip.presentation.component.card.BbangZipCardState import org.android.bbangzip.presentation.model.card.ToDoCardModel +import org.android.bbangzip.presentation.type.ToDoFilterType import org.android.bbangzip.presentation.type.ToDoScreenType import org.android.bbangzip.presentation.util.base.BaseContract @@ -125,7 +126,7 @@ class TodoContract { val remainingStudyCount: Int = 5, val completeCount: Int = 5, val todoFilterBottomSheetState: Boolean = false, - val todoFilterItemIndex: Int = 0, + val selectedFilterItem: ToDoFilterType = ToDoFilterType.RECENT, val selectedItemList: List = listOf(), val revertCompleteBottomSheetState: Boolean = false, val screenType: ToDoScreenType = ToDoScreenType.DEFAULT @@ -166,7 +167,7 @@ class TodoContract { val completeCount: Int ) : TodoEvent - data class OnFilterBottomSheetItemClicked(val todoFilterItemIndex: Int) : TodoEvent + data class OnFilterBottomSheetItemClicked(val selectedFilterItem: ToDoFilterType) : TodoEvent data class OnDeleteScreenCardClicked(val pieceId: Int,val cardState: BbangZipCardState) : TodoEvent @@ -202,11 +203,10 @@ class TodoContract { data class UpdateToDoListCardState( val previousCardState: BbangZipCardState, val nextCardState: BbangZipCardState - ) : TodoReduce - data class UpdateFilterItemIndex( - val itemIndex: Int + data class UpdateFilterType( + val selectedFilter: ToDoFilterType ) : TodoReduce data class UpdatePendingToDoCount(val pendingCount: Int) : TodoReduce diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt index dac4895c..1fade72d 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt @@ -7,7 +7,9 @@ import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle +import kotlinx.coroutines.delay import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch import java.time.LocalDateTime import java.time.format.DateTimeFormatter import java.util.Locale @@ -32,8 +34,15 @@ fun TodoRoute( TodoContract.TodoSideEffect.NavigateToAddToDo -> navigateToAddToDo() - is TodoContract.TodoSideEffect.ShowSnackBar -> - snackBarHostState.showSnackbar(effect.message) + is TodoContract.TodoSideEffect.ShowSnackBar -> { + val job = + launch { + snackBarHostState.currentSnackbarData?.dismiss() + snackBarHostState.showSnackbar(effect.message) + } + delay(2000) + job.cancel() + } } } } @@ -43,7 +52,6 @@ fun TodoRoute( TodoScreen( todoState = todoState, todayDate = todayDate, - snackBarHostState = snackBarHostState, onAddPendingStudyButtonClicked = { viewModel.setEvent(TodoContract.TodoEvent.OnAddPendingStudyButtonClicked) }, @@ -59,13 +67,13 @@ fun TodoRoute( ) }, onRevertCompleteBottomSheetDismissRequest = { - viewModel.setEvent(TodoContract.TodoEvent.OnFilterBottomSheetDismissRequest) + viewModel.setEvent(TodoContract.TodoEvent.OnRevertCompleteBottomSheetDismissRequest) }, onFilterIconClicked = { viewModel.setEvent(TodoContract.TodoEvent.OnFilterIconClicked) }, - onFilterBottomSheetItemClicked = { filterIndex -> - viewModel.setEvent(TodoContract.TodoEvent.OnFilterBottomSheetItemClicked(todoFilterItemIndex = filterIndex)) + onFilterBottomSheetItemClicked = { selectedFilter -> + viewModel.setEvent(TodoContract.TodoEvent.OnFilterBottomSheetItemClicked(selectedFilterItem = selectedFilter)) }, onFilterBottomSheetDismissRequest = { viewModel.setEvent(TodoContract.TodoEvent.OnFilterBottomSheetDismissRequest) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt index fdfe5ac3..4a29f977 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt @@ -2,8 +2,10 @@ package org.android.bbangzip.presentation.ui.todo import androidx.compose.foundation.background import androidx.compose.foundation.clickable +import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column +import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -13,10 +15,11 @@ import androidx.compose.foundation.layout.padding import androidx.compose.foundation.layout.width import androidx.compose.foundation.layout.wrapContentSize import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.itemsIndexed import androidx.compose.foundation.shape.CircleShape import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.Icon -import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.ui.Alignment @@ -26,25 +29,27 @@ import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.platform.LocalConfiguration import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.text.style.TextAlign import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import org.android.bbangzip.R import org.android.bbangzip.presentation.component.balloon.TopTailBalloon +import org.android.bbangzip.presentation.component.bottomsheet.BbangZipBasicModalBottomSheet import org.android.bbangzip.presentation.component.button.BbangZipButton import org.android.bbangzip.presentation.component.card.BbangZipCardState import org.android.bbangzip.presentation.component.card.ToDoCard -import org.android.bbangzip.presentation.component.snackbar.BbangZipSnackBarHost import org.android.bbangzip.presentation.model.card.ToDoCardModel import org.android.bbangzip.presentation.type.BbangZipButtonSize import org.android.bbangzip.presentation.type.BbangZipButtonType +import org.android.bbangzip.presentation.type.ToDoFilterType import org.android.bbangzip.presentation.type.ToDoScreenType +import org.android.bbangzip.presentation.util.modifier.applyFilterOnClick import org.android.bbangzip.ui.theme.BbangZipTheme @Composable fun TodoScreen( todoState: TodoContract.TodoState, todayDate: List, - snackBarHostState: SnackbarHostState, modifier: Modifier = Modifier, onAddPendingStudyButtonClicked: () -> Unit = {}, onAddStudyButtonClicked: () -> Unit = {}, @@ -52,7 +57,7 @@ fun TodoScreen( onRevertCompleteBottomSheetApproveButtonClicked: (Int) -> Unit = {}, onRevertCompleteBottomSheetDismissRequest: () -> Unit = {}, onFilterIconClicked: () -> Unit = {}, - onFilterBottomSheetItemClicked: (Int) -> Unit = {}, + onFilterBottomSheetItemClicked: (ToDoFilterType) -> Unit = {}, onFilterBottomSheetDismissRequest: () -> Unit = {}, onDeleteIconClicked: () -> Unit = {}, onCloseIconClicked: () -> Unit = {}, @@ -60,13 +65,13 @@ fun TodoScreen( onDeleteScreenCardClicked: (Int, BbangZipCardState) -> Unit = { _, _ -> }, onDefaultScreenCardClicked: (Int, BbangZipCardState) -> Unit = { _, _ -> }, ) { - Box(modifier = Modifier.fillMaxSize()) { - LazyColumn( - modifier = modifier - .fillMaxSize() - .background(color = BbangZipTheme.colors.staticWhite_FFFFFF) - .padding(bottom = 74.dp) - ) { + Box( + modifier = modifier + .fillMaxSize() + .padding(bottom = 74.dp) + .background(color = BbangZipTheme.colors.staticWhite_FFFFFF) + ) { + LazyColumn { item { DateMessageCard( todayDate = todayDate, @@ -182,27 +187,38 @@ fun TodoScreen( ) } } - if (todoState.screenType == ToDoScreenType.DELETE) { - item { - Spacer(modifier = Modifier.height(10.dp)) - - BbangZipButton( - bbangZipButtonType = BbangZipButtonType.Solid, - bbangZipButtonSize = BbangZipButtonSize.Large, - onClick = { onItemDeleteButtonClicked() }, - label = stringResource(R.string.todo_delete_screen_delete_button_text, todoState.selectedItemList.size), - modifier = Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth(), - isEnable = todoState.selectedItemList.isNotEmpty(), - trailingIcon = R.drawable.ic_plus_thick_24, - ) + } + if (todoState.screenType == ToDoScreenType.DELETE) { + BbangZipButton( + bbangZipButtonType = BbangZipButtonType.Solid, + bbangZipButtonSize = BbangZipButtonSize.Large, + onClick = { onItemDeleteButtonClicked() }, + label = stringResource(R.string.todo_delete_screen_delete_button_text, todoState.selectedItemList.size), + modifier = Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth() + .align(Alignment.BottomCenter) + .padding(bottom = 6.dp), + isEnable = todoState.selectedItemList.isNotEmpty(), + trailingIcon = R.drawable.ic_plus_thick_24, + ) + } - Spacer(modifier = Modifier.height(16.dp)) + RevertCompleteBottomSheet( + isBottomSheetVisible = todoState.revertCompleteBottomSheetState, + selectedItemPieceId = todoState.selectedItemList, + bottomSheetTitle = "미완료 상태로 되돌릴까요?", + onDismissRequest = onRevertCompleteBottomSheetDismissButtonClicked, + onClickInteractButton = onRevertCompleteBottomSheetApproveButtonClicked, + onClickCancelButton = onRevertCompleteBottomSheetDismissButtonClicked + ) - } - } - } + BbangZipToDoFilterPickerBottomSheet( + isBottomSheetVisible = todoState.todoFilterBottomSheetState, + selectedItem = todoState.selectedFilterItem, + onSelectedItemChanged = onFilterBottomSheetItemClicked, + onDismissRequest = onFilterBottomSheetDismissRequest + ) } } @@ -325,7 +341,7 @@ fun StudyCountText( ) { Text( text = when { - completeCount > 0 && remainingCount != 0-> stringResource(R.string.todo_complete_count_text, completeCount) + completeCount > 0 && remainingCount != 0 -> stringResource(R.string.todo_complete_count_text, completeCount) remainingCount == 0 -> stringResource(R.string.todo_complete_remaining_nothing_text) else -> stringResource(R.string.todo_complete_nothing_text) }, @@ -413,6 +429,104 @@ fun EmptyView( } } +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun BbangZipToDoFilterPickerBottomSheet( + isBottomSheetVisible: Boolean, + modifier: Modifier = Modifier, + title: @Composable (ColumnScope.() -> Unit) = {}, + selectedItem: ToDoFilterType = ToDoFilterType.RECENT, + onSelectedItemChanged: (ToDoFilterType) -> Unit = {}, + onDismissRequest: () -> Unit = {}, +) { + BbangZipBasicModalBottomSheet( + modifier = modifier, + isBottomSheetVisible = isBottomSheetVisible, + onDismissRequest = onDismissRequest, + title = { title() }, + content = { + LazyColumn( + modifier = Modifier.padding(top = 8.dp, bottom = 24.dp), + verticalArrangement = Arrangement.spacedBy(8.dp), + horizontalAlignment = Alignment.CenterHorizontally, + ) { + itemsIndexed( + ToDoFilterType.entries, + key = { _, item -> item }, + ) { _, item -> + Text( + text = item.filter, + modifier = + Modifier + .fillMaxWidth() + .applyFilterOnClick { onSelectedItemChanged(item) } + .background( + color = if (item != selectedItem) BbangZipTheme.colors.staticWhite_FFFFFF else BbangZipTheme.colors.fillStrong_68645E_16, + shape = RoundedCornerShape(16.dp), + ) + .padding(vertical = 8.dp), + textAlign = TextAlign.Center, + style = BbangZipTheme.typography.body1Bold, + color = BbangZipTheme.colors.labelNormal_282119, + ) + } + } + }, + ) +} + +@OptIn(ExperimentalMaterial3Api::class) +@Composable +fun RevertCompleteBottomSheet( + isBottomSheetVisible: Boolean, + selectedItemPieceId: List, + bottomSheetTitle: String, + modifier: Modifier = Modifier, + onDismissRequest: () -> Unit = {}, + onClickInteractButton: (Int) -> Unit = {}, + onClickCancelButton: () -> Unit = {}, +) { + BbangZipBasicModalBottomSheet( + modifier = modifier, + isBottomSheetVisible = isBottomSheetVisible, + onDismissRequest = onDismissRequest, + title = { + Text( + text = bottomSheetTitle, + modifier = + Modifier + .align(Alignment.CenterHorizontally) + .padding(vertical = 15.dp), + style = BbangZipTheme.typography.headline1Bold, + color = BbangZipTheme.colors.labelNeutral_282119_88, + ) + }, + interactButton = { + Spacer(modifier = Modifier.height(16.dp)) + + BbangZipButton( + bbangZipButtonType = BbangZipButtonType.Solid, + bbangZipButtonSize = BbangZipButtonSize.Large, + onClick = { onClickInteractButton(selectedItemPieceId[0]) }, + label = stringResource(R.string.todo_revert_bottomsheet_approve_text), + modifier = Modifier.fillMaxWidth(), + ) + }, + cancelButton = { + Spacer(modifier = Modifier.height(8.dp)) + + BbangZipButton( + bbangZipButtonType = BbangZipButtonType.Outlined, + bbangZipButtonSize = BbangZipButtonSize.Large, + onClick = onClickCancelButton, + label = stringResource(R.string.btn_cancle_label), + modifier = Modifier.fillMaxWidth(), + ) + }, + ) +} + + @Preview(showBackground = true) @Composable fun TodoScreenMockPreview() { @@ -589,6 +703,5 @@ fun TodoScreenMockPreview() { TodoScreen( todoState = mockTodoStates[0], todayDate = listOf("2025", "01", "18"), - snackBarHostState = SnackbarHostState() ) } \ No newline at end of file diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt index 5f5f66b5..ece31ecb 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt @@ -4,10 +4,8 @@ import android.os.Parcelable import androidx.lifecycle.SavedStateHandle import dagger.hilt.android.lifecycle.HiltViewModel import org.android.bbangzip.presentation.component.card.BbangZipCardState -import org.android.bbangzip.presentation.type.ToDoFilterType import org.android.bbangzip.presentation.type.ToDoScreenType import org.android.bbangzip.presentation.util.base.BaseViewModel -import timber.log.Timber import javax.inject.Inject @HiltViewModel @@ -42,40 +40,94 @@ constructor( //Filter BottomSheet is TodoContract.TodoEvent.OnFilterBottomSheetItemClicked -> { - updateState(TodoContract.TodoReduce.UpdateFilterItemIndex(itemIndex = event.todoFilterItemIndex)) - setSideEffect(TodoContract.TodoSideEffect.ShowSnackBar("${ToDoFilterType.entries[event.todoFilterItemIndex].id}으로 정렬했어요")) + updateState(TodoContract.TodoReduce.UpdateFilterType(selectedFilter = event.selectedFilterItem)) + updateState( + TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = false + ) + ) + setSideEffect(TodoContract.TodoSideEffect.ShowSnackBar("${event.selectedFilterItem.filter}으로 정렬했어요")) //TODO index를 이용해 서버로 FetchInfo 이름 보내주기 } - TodoContract.TodoEvent.OnFilterBottomSheetDismissRequest -> updateState(TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState(todoFilterBottomSheetState = false)) + TodoContract.TodoEvent.OnFilterBottomSheetDismissRequest -> updateState( + TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = false + ) + ) + TodoContract.TodoEvent.OnFilterIconClicked -> { - updateState(TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState(todoFilterBottomSheetState = true)) + updateState( + TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = true + ) + ) } //revertComplete BottomSheet is TodoContract.TodoEvent.OnRevertCompleteBottomSheetApproveButtonClicked -> { - updateState(TodoContract.TodoReduce.UpdateCardState(pieceId = event.pieceId, cardState = BbangZipCardState.DEFAULT)) - updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = false)) - updateState(TodoContract.TodoReduce.UpdateToDoCount(completeCount = currentUiState.completeCount - 1, remainingStudyCount = currentUiState.remainingStudyCount + 1)) + updateState( + TodoContract.TodoReduce.UpdateCardState( + pieceId = event.pieceId, + cardState = BbangZipCardState.DEFAULT + ) + ) + updateState( + TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState( + revertCompleteBottomSheetState = false + ) + ) + updateState( + TodoContract.TodoReduce.UpdateToDoCount( + completeCount = currentUiState.completeCount - 1, + remainingStudyCount = currentUiState.remainingStudyCount + 1 + ) + ) + updateState(TodoContract.TodoReduce.ResetSelectedItemList) setSideEffect(TodoContract.TodoSideEffect.ShowSnackBar("미완료 상태로 되돌려졌어요!")) //TODO pieceId 사영헤사 서버로 쏘기 미완료 APT } - TodoContract.TodoEvent.OnRevertCompleteBottomSheetDismissButtonClicked -> updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = false)) - TodoContract.TodoEvent.OnRevertCompleteBottomSheetDismissRequest -> updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = false)) + TodoContract.TodoEvent.OnRevertCompleteBottomSheetDismissButtonClicked -> { + updateState( + TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState( + revertCompleteBottomSheetState = false + ) + ) + updateState(TodoContract.TodoReduce.ResetSelectedItemList) + } + + TodoContract.TodoEvent.OnRevertCompleteBottomSheetDismissRequest -> { + updateState( + TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState( + revertCompleteBottomSheetState = false + ) + ) + updateState(TodoContract.TodoReduce.ResetSelectedItemList) + } //Delete is TodoContract.TodoEvent.OnDeleteScreenCardClicked -> { when (event.cardState) { BbangZipCardState.CHECKED -> { updateState(TodoContract.TodoReduce.UpdateSelectedItemList(pieceId = event.pieceId)) - updateState(TodoContract.TodoReduce.UpdateCardState(pieceId = event.pieceId, cardState = event.cardState)) + updateState( + TodoContract.TodoReduce.UpdateCardState( + pieceId = event.pieceId, + cardState = event.cardState + ) + ) } BbangZipCardState.CHECKABLE -> { updateState(TodoContract.TodoReduce.DeleteSelectedItemList(pieceId = event.pieceId)) - updateState(TodoContract.TodoReduce.UpdateCardState(pieceId = event.pieceId, cardState = event.cardState)) + updateState( + TodoContract.TodoReduce.UpdateCardState( + pieceId = event.pieceId, + cardState = event.cardState + ) + ) } else -> { @@ -86,11 +138,27 @@ constructor( //Default is TodoContract.TodoEvent.OnDefaultScreenCardClicked -> { if (event.cardState == BbangZipCardState.COMPLETE) { - updateState(TodoContract.TodoReduce.UpdateCardState(pieceId = event.pieceId, cardState = event.cardState)) - updateState(TodoContract.TodoReduce.UpdateToDoCount(completeCount = currentUiState.completeCount + 1, remainingStudyCount = currentUiState.remainingStudyCount - 1)) + updateState( + TodoContract.TodoReduce.UpdateCardState( + pieceId = event.pieceId, + cardState = event.cardState + ) + ) + updateState( + TodoContract.TodoReduce.UpdateToDoCount( + completeCount = currentUiState.completeCount + 1, + remainingStudyCount = currentUiState.remainingStudyCount - 1 + ) + ) TodoContract.TodoSideEffect.ShowSnackBar("공부완료 ! 오늘의 빵굽기 성공!") } else { - updateState(TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState(revertCompleteBottomSheetState = true)) + updateState( + TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState( + revertCompleteBottomSheetState = true + ) + ) + updateState(TodoContract.TodoReduce.UpdateSelectedItemList(pieceId = event.pieceId)) + } // TODO 서버로 pieceId 이용해서 완료 API 쏘기 } @@ -115,7 +183,12 @@ constructor( ) if (currentUiState.remainingStudyCount != 0) { updateState(TodoContract.TodoReduce.DeleteToDoListItems) - updateState(TodoContract.TodoReduce.UpdateToDoListCardState(previousCardState = BbangZipCardState.CHECKABLE, nextCardState = BbangZipCardState.DEFAULT)) + updateState( + TodoContract.TodoReduce.UpdateToDoListCardState( + previousCardState = BbangZipCardState.CHECKABLE, + nextCardState = BbangZipCardState.DEFAULT + ) + ) updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.DEFAULT)) } else { @@ -126,8 +199,18 @@ constructor( } // 통과 TodoContract.TodoEvent.OnCloseIconClicked -> { - updateState(TodoContract.TodoReduce.UpdateToDoListCardState(previousCardState = BbangZipCardState.CHECKABLE, nextCardState = BbangZipCardState.DEFAULT)) - updateState(TodoContract.TodoReduce.UpdateToDoListCardState(previousCardState = BbangZipCardState.CHECKED, nextCardState = BbangZipCardState.DEFAULT)) + updateState( + TodoContract.TodoReduce.UpdateToDoListCardState( + previousCardState = BbangZipCardState.CHECKABLE, + nextCardState = BbangZipCardState.DEFAULT + ) + ) + updateState( + TodoContract.TodoReduce.UpdateToDoListCardState( + previousCardState = BbangZipCardState.CHECKED, + nextCardState = BbangZipCardState.DEFAULT + ) + ) updateState(TodoContract.TodoReduce.ResetSelectedItemList) updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.DEFAULT)) } @@ -138,7 +221,10 @@ constructor( } } - override fun reduceState(state: TodoContract.TodoState, reduce: TodoContract.TodoReduce): TodoContract.TodoState { + override fun reduceState( + state: TodoContract.TodoState, + reduce: TodoContract.TodoReduce + ): TodoContract.TodoState { return when (reduce) { //ToDoInfo Fetch is TodoContract.TodoReduce.UpdateToDoInfo -> state.copy( @@ -174,7 +260,7 @@ constructor( //Revert BottomSheet is TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState -> state.copy( - revertCompleteBottomSheetState = !state.revertCompleteBottomSheetState + revertCompleteBottomSheetState = reduce.revertCompleteBottomSheetState ) is TodoContract.TodoReduce.UpdateSelectedItemList -> state.copy( @@ -187,17 +273,18 @@ constructor( //Filter BottomSheet is TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState -> state.copy( - todoFilterBottomSheetState = !state.todoFilterBottomSheetState + todoFilterBottomSheetState = reduce.todoFilterBottomSheetState ) - is TodoContract.TodoReduce.UpdateFilterItemIndex -> state.copy( - todoFilterItemIndex = reduce.itemIndex + is TodoContract.TodoReduce.UpdateFilterType -> state.copy( + selectedFilterItem = reduce.selectedFilter ) //ToDoCount is TodoContract.TodoReduce.UpdateToDoCount -> { state.copy( - completeCount = reduce.completeCount, remainingStudyCount = reduce.remainingStudyCount + completeCount = reduce.completeCount, + remainingStudyCount = reduce.remainingStudyCount ) } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index dc0d4659..a74067a3 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -69,14 +69,14 @@ %s/%s - recent - leastVolume - nearestDeadline + 최근 등록 순 + 분량 적은 순 + 마감 기한 빠른 순 사장님의 밀린 공부는 빵 개! 사장님의 과제 빵점 탈출을 응원해요! - 벌써 %s개나 완료 하셨네요 + 벌써 %s개나 완료 하셨네요! 아직 완료된 할일이 없네요! 총 %s개의 공부가 남았어요 오늘의 공부를 모두 끝냈어요! @@ -87,4 +87,5 @@ 제 과제 빵점 사장님은\n이번 학기 백점! 5초 만에 빵집 사장님 되기 + 되돌리기 \ No newline at end of file From 62ebe0facd8032e84ac01fd9207dad3bf1aebb83 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sun, 19 Jan 2025 04:46:16 +0900 Subject: [PATCH 23/40] =?UTF-8?q?[feat]=20#31=20ToDoAddCContract=20?= =?UTF-8?q?=EA=B5=AC=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/ui/navigator/MainNavHost.kt | 2 +- .../ui/navigator/MainNavigator.kt | 2 +- .../presentation/ui/todo/TodoContract.kt | 12 +++- .../todo/{ => navigation}/TodoNavigation.kt | 3 +- .../ui/todo/todoadd/TodoAddContract.kt | 67 +++++++++++++++++++ 5 files changed, 80 insertions(+), 6 deletions(-) rename app/src/main/java/org/android/bbangzip/presentation/ui/todo/{ => navigation}/TodoNavigation.kt (84%) create mode 100644 app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddContract.kt diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt index 7268fa5f..8a8c1f80 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt @@ -14,7 +14,7 @@ import org.android.bbangzip.presentation.ui.login.loginNavGraph import org.android.bbangzip.presentation.ui.my.myNavGraph import org.android.bbangzip.presentation.ui.subject.navigateSubject import org.android.bbangzip.presentation.ui.subject.subjectNavGraph -import org.android.bbangzip.presentation.ui.todo.todoNavGraph +import org.android.bbangzip.presentation.ui.todo.navigation.todoNavGraph import org.android.bbangzip.ui.theme.BbangZipTheme @Composable diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt index bb00ae87..9ec9a30a 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt @@ -16,7 +16,7 @@ import org.android.bbangzip.presentation.ui.login.LoginRoute import org.android.bbangzip.presentation.ui.login.navigateLogin import org.android.bbangzip.presentation.ui.my.navigateMy import org.android.bbangzip.presentation.ui.subject.navigateSubject -import org.android.bbangzip.presentation.ui.todo.navigateTodo +import org.android.bbangzip.presentation.ui.todo.navigation.navigateTodo import timber.log.Timber class MainNavigator( diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt index 2949a5e1..4a5bac9b 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt @@ -155,7 +155,6 @@ class TodoContract { data object OnItemDeleteButtonClicked : TodoEvent - data class OnRevertCompleteBottomSheetApproveButtonClicked( val pieceId: Int, ) : TodoEvent @@ -167,9 +166,15 @@ class TodoContract { val completeCount: Int ) : TodoEvent - data class OnFilterBottomSheetItemClicked(val selectedFilterItem: ToDoFilterType) : TodoEvent + data class OnFilterBottomSheetItemClicked( + val selectedFilterItem: ToDoFilterType + ) : TodoEvent - data class OnDeleteScreenCardClicked(val pieceId: Int,val cardState: BbangZipCardState) : TodoEvent + data class OnDeleteScreenCardClicked( + val pieceId: Int, + val cardState: BbangZipCardState + ) : + TodoEvent data class OnDefaultScreenCardClicked( val pieceId: Int, @@ -184,6 +189,7 @@ class TodoContract { val remainingStudyCount: Int, val completeCount: Int, ) : TodoReduce + data object DeleteToDoListItems : TodoReduce data class UpdateToDoFilterBottomSheetState(val todoFilterBottomSheetState: Boolean) : diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoNavigation.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt similarity index 84% rename from app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoNavigation.kt rename to app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt index bacbc1cd..94967fbd 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoNavigation.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt @@ -1,4 +1,4 @@ -package org.android.bbangzip.presentation.ui.todo +package org.android.bbangzip.presentation.ui.todo.navigation import androidx.compose.material3.SnackbarHostState import androidx.navigation.NavController @@ -6,6 +6,7 @@ import androidx.navigation.NavGraphBuilder import androidx.navigation.NavOptions import androidx.navigation.compose.composable import org.android.bbangzip.presentation.model.BottomNavigationRoute +import org.android.bbangzip.presentation.ui.todo.TodoRoute fun NavController.navigateTodo(navOptions: NavOptions) { navigate( diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddContract.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddContract.kt new file mode 100644 index 00000000..cf372cb2 --- /dev/null +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddContract.kt @@ -0,0 +1,67 @@ +package org.android.bbangzip.presentation.ui.todo.todoadd + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize +import org.android.bbangzip.presentation.component.card.BbangZipCardState +import org.android.bbangzip.presentation.model.card.ToDoCardModel +import org.android.bbangzip.presentation.type.ToDoFilterType +import org.android.bbangzip.presentation.type.ToDoScreenType +import org.android.bbangzip.presentation.ui.todo.TodoContract.TodoEvent +import org.android.bbangzip.presentation.ui.todo.TodoContract.TodoReduce +import org.android.bbangzip.presentation.util.base.BaseContract + +class TodoContract { + @Parcelize + data class TodoAddState( + val todoList: List = listOf(), + val todoFilterBottomSheetState: Boolean = false, + val selectedItemList: List = listOf(), + ) : BaseContract.State, Parcelable { + override fun toParcelable(): Parcelable = this + } + + sealed interface TodoAddEvent : BaseContract.Event { + data object Initialize : TodoAddEvent + + data object OnFilterIconClicked : TodoAddEvent + + data object OnBackIconClicked : TodoAddEvent + + data object OnFilterBottomSheetDismissRequest : TodoAddEvent + + data object OnItemPlusButtonClicked : TodoAddEvent + + data class OnFilterBottomSheetItemClicked(val selectedFilterItem: ToDoFilterType) : TodoAddEvent + + data class OnToDoCardClicked(val pieceId: Int, val cardState: BbangZipCardState) : TodoAddEvent + } + + sealed interface TodoAddReduce : BaseContract.Reduce { + data object ResetSelectedItemList : TodoAddReduce + + data class UpdateSelectedItemList( + val pieceId: Int + ) : TodoAddReduce + + data class UpdateToDoFilterBottomSheetState( + val todoFilterBottomSheetState: Boolean + ) : TodoAddReduce + + data class UpdateFilterType( + val selectedFilter: ToDoFilterType + ) : TodoAddReduce + + data class UpdateCardState( + val pieceId: Int, + val cardState: BbangZipCardState + ) : TodoAddReduce + } + + sealed interface TodoAddSideEffect : BaseContract.SideEffect { + data object NavigateToToDo : TodoAddSideEffect + + data object NavigateToBack : TodoAddSideEffect + + data class ShowSnackBar(val message: String) : TodoAddSideEffect + } +} \ No newline at end of file From e540d150f21aef5b278bf34410118ec78ff9b361 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sun, 19 Jan 2025 05:49:04 +0900 Subject: [PATCH 24/40] =?UTF-8?q?[feat]=20#31=20ToDoAdd=20naviagation=20?= =?UTF-8?q?=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/ui/navigator/MainNavHost.kt | 25 +++++++++++++---- .../ui/navigator/MainNavigator.kt | 17 +++++++++++ .../ui/todo/navigation/TodoNavigation.kt | 11 ++++++-- .../ui/todo/todoadd/TodoAddContract.kt | 10 ++++--- .../todoadd/navigation/TodoAddNavigation.kt | 28 +++++++++++++++++++ 5 files changed, 80 insertions(+), 11 deletions(-) create mode 100644 app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/navigation/TodoAddNavigation.kt diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt index 8a8c1f80..1b290cae 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt @@ -9,12 +9,15 @@ import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.navigation.compose.NavHost +import androidx.navigation.navOptions import org.android.bbangzip.presentation.ui.friend.friendNavGraph import org.android.bbangzip.presentation.ui.login.loginNavGraph import org.android.bbangzip.presentation.ui.my.myNavGraph import org.android.bbangzip.presentation.ui.subject.navigateSubject import org.android.bbangzip.presentation.ui.subject.subjectNavGraph +import org.android.bbangzip.presentation.ui.todo.navigation.navigateTodo import org.android.bbangzip.presentation.ui.todo.navigation.todoNavGraph +import org.android.bbangzip.presentation.ui.todo.todoadd.navigation.todoAddNavGraph import org.android.bbangzip.ui.theme.BbangZipTheme @Composable @@ -26,10 +29,10 @@ fun MainNavHost( ) { Box( modifier = - modifier - .padding(top = padding.calculateTopPadding()) - .fillMaxSize() - .background(BbangZipTheme.colors.backgroundNormal_FFFFFF), + modifier + .padding(top = padding.calculateTopPadding()) + .fillMaxSize() + .background(BbangZipTheme.colors.backgroundNormal_FFFFFF), ) { NavHost( navController = navigator.navHostController, @@ -43,13 +46,25 @@ fun MainNavHost( }, ) + todoAddNavGraph( + navigateToBack = { navigator.popBackStackIfNotSubject() }, + navigateToToDo = { + navigator.navHostController.navigateTodo(navOptions = + navOptions { launchSingleTop = true }) + } + ) + friendNavGraph() myNavGraph() subjectNavGraph() - todoNavGraph(snackBarHostState = snackBarHostState) + todoNavGraph( + snackBarHostState = snackBarHostState, + navigateToAddToDo = { navigator.navigateToToDoAdd() }, + navigateToAddPendingToDo = {}, + ) } } } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt index 9ec9a30a..a996d0be 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt @@ -17,6 +17,7 @@ import org.android.bbangzip.presentation.ui.login.navigateLogin import org.android.bbangzip.presentation.ui.my.navigateMy import org.android.bbangzip.presentation.ui.subject.navigateSubject import org.android.bbangzip.presentation.ui.todo.navigation.navigateTodo +import org.android.bbangzip.presentation.ui.todo.todoadd.navigation.navigateTodoAdd import timber.log.Timber class MainNavigator( @@ -62,10 +63,26 @@ class MainNavigator( navHostController.navigateLogin() } + fun navigateToToDo() { + navHostController.navigateTodo(navOptions { + popUpTo(BottomNavigationRoute.Subject::class.qualifiedName.orEmpty()) { + saveState = true + Timber.d("[navigation] restoreState -> $saveState") + } + launchSingleTop = true + restoreState = true + }) + } + + fun navigateToToDoAdd() { + navHostController.navigateTodoAdd() + } + private fun popBackStack() { navHostController.popBackStack() } + fun popBackStackIfNotSubject() { if (!isSameCurrentDestination()) { popBackStack() diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt index 94967fbd..933484ad 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt @@ -15,8 +15,15 @@ fun NavController.navigateTodo(navOptions: NavOptions) { ) } -fun NavGraphBuilder.todoNavGraph(snackBarHostState: SnackbarHostState) { +fun NavGraphBuilder.todoNavGraph( + snackBarHostState: SnackbarHostState, + navigateToAddToDo: () -> Unit, + navigateToAddPendingToDo: () -> Unit = {} +) { composable { - TodoRoute(snackBarHostState = snackBarHostState) + TodoRoute( + snackBarHostState = snackBarHostState, + navigateToAddToDo = navigateToAddToDo + ) } } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddContract.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddContract.kt index cf372cb2..10028392 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddContract.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddContract.kt @@ -5,16 +5,14 @@ import kotlinx.parcelize.Parcelize import org.android.bbangzip.presentation.component.card.BbangZipCardState import org.android.bbangzip.presentation.model.card.ToDoCardModel import org.android.bbangzip.presentation.type.ToDoFilterType -import org.android.bbangzip.presentation.type.ToDoScreenType -import org.android.bbangzip.presentation.ui.todo.TodoContract.TodoEvent -import org.android.bbangzip.presentation.ui.todo.TodoContract.TodoReduce import org.android.bbangzip.presentation.util.base.BaseContract -class TodoContract { +class TodoAddContract { @Parcelize data class TodoAddState( val todoList: List = listOf(), val todoFilterBottomSheetState: Boolean = false, + val selectedFilter: ToDoFilterType = ToDoFilterType.RECENT, val selectedItemList: List = listOf(), ) : BaseContract.State, Parcelable { override fun toParcelable(): Parcelable = this @@ -51,6 +49,10 @@ class TodoContract { val selectedFilter: ToDoFilterType ) : TodoAddReduce + data class DeleteSelectedItemList( + val pieceId: Int + ) : TodoAddReduce + data class UpdateCardState( val pieceId: Int, val cardState: BbangZipCardState diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/navigation/TodoAddNavigation.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/navigation/TodoAddNavigation.kt new file mode 100644 index 00000000..a48df751 --- /dev/null +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/navigation/TodoAddNavigation.kt @@ -0,0 +1,28 @@ +package org.android.bbangzip.presentation.ui.todo.todoadd.navigation + +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.compose.composable +import kotlinx.serialization.Serializable +import org.android.bbangzip.presentation.ui.todo.todoadd.TodoAddRoute + +@Serializable +object TodoAddRoute + +fun NavController.navigateTodoAdd() { + navigate( + route = TodoAddRoute, + ) +} + +fun NavGraphBuilder.todoAddNavGraph( + navigateToToDo: () -> Unit, + navigateToBack: () -> Unit, +) { + composable { + TodoAddRoute( + navigateToToDo = navigateToToDo, + navigateToBack = navigateToBack, + ) + } +} \ No newline at end of file From be8e87c718287c974f26dcae8aa5888cea064c26 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sun, 19 Jan 2025 06:13:28 +0900 Subject: [PATCH 25/40] =?UTF-8?q?[feat]=20#31=20ToDoAdd=20naviagation=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 --- .../bbangzip/presentation/ui/navigator/MainNavHost.kt | 9 +++------ .../bbangzip/presentation/ui/todo/TodoContract.kt | 2 +- .../android/bbangzip/presentation/ui/todo/TodoScreen.kt | 2 +- .../ui/todo/todoadd/navigation/TodoAddNavigation.kt | 3 +++ 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt index 1b290cae..52428c2b 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt @@ -9,13 +9,11 @@ import androidx.compose.material3.SnackbarHostState import androidx.compose.runtime.Composable import androidx.compose.ui.Modifier import androidx.navigation.compose.NavHost -import androidx.navigation.navOptions import org.android.bbangzip.presentation.ui.friend.friendNavGraph import org.android.bbangzip.presentation.ui.login.loginNavGraph import org.android.bbangzip.presentation.ui.my.myNavGraph import org.android.bbangzip.presentation.ui.subject.navigateSubject import org.android.bbangzip.presentation.ui.subject.subjectNavGraph -import org.android.bbangzip.presentation.ui.todo.navigation.navigateTodo import org.android.bbangzip.presentation.ui.todo.navigation.todoNavGraph import org.android.bbangzip.presentation.ui.todo.todoadd.navigation.todoAddNavGraph import org.android.bbangzip.ui.theme.BbangZipTheme @@ -47,13 +45,12 @@ fun MainNavHost( ) todoAddNavGraph( + snackBarHostState = snackBarHostState, navigateToBack = { navigator.popBackStackIfNotSubject() }, - navigateToToDo = { - navigator.navHostController.navigateTodo(navOptions = - navOptions { launchSingleTop = true }) - } + navigateToToDo = { navigator.navigateToToDo() } ) + friendNavGraph() myNavGraph() diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt index 4a5bac9b..de87cdd8 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt @@ -129,7 +129,7 @@ class TodoContract { val selectedFilterItem: ToDoFilterType = ToDoFilterType.RECENT, val selectedItemList: List = listOf(), val revertCompleteBottomSheetState: Boolean = false, - val screenType: ToDoScreenType = ToDoScreenType.DEFAULT + val screenType: ToDoScreenType = ToDoScreenType.EMPTY ) : BaseContract.State, Parcelable { override fun toParcelable(): Parcelable = this } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt index 4a29f977..d7072cdb 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt @@ -208,7 +208,7 @@ fun TodoScreen( isBottomSheetVisible = todoState.revertCompleteBottomSheetState, selectedItemPieceId = todoState.selectedItemList, bottomSheetTitle = "미완료 상태로 되돌릴까요?", - onDismissRequest = onRevertCompleteBottomSheetDismissButtonClicked, + onDismissRequest = onRevertCompleteBottomSheetDismissRequest, onClickInteractButton = onRevertCompleteBottomSheetApproveButtonClicked, onClickCancelButton = onRevertCompleteBottomSheetDismissButtonClicked ) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/navigation/TodoAddNavigation.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/navigation/TodoAddNavigation.kt index a48df751..d116c96f 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/navigation/TodoAddNavigation.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/navigation/TodoAddNavigation.kt @@ -1,5 +1,6 @@ package org.android.bbangzip.presentation.ui.todo.todoadd.navigation +import androidx.compose.material3.SnackbarHostState import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder import androidx.navigation.compose.composable @@ -16,11 +17,13 @@ fun NavController.navigateTodoAdd() { } fun NavGraphBuilder.todoAddNavGraph( + snackBarHostState: SnackbarHostState, navigateToToDo: () -> Unit, navigateToBack: () -> Unit, ) { composable { TodoAddRoute( + snackBarHostState = snackBarHostState, navigateToToDo = navigateToToDo, navigateToBack = navigateToBack, ) From b7d588bd8a226e69c193562202c926a3dbebd793 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sun, 19 Jan 2025 06:14:05 +0900 Subject: [PATCH 26/40] =?UTF-8?q?[feat]=20#31=20ToDoAddRoute=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/ui/todo/TodoViewModel.kt | 2 +- .../ui/todo/todoadd/TodoAddRoute.kt | 73 ++++++++++++ .../ui/todo/todoadd/TodoAddScreen.kt | 20 ++++ .../ui/todo/todoadd/TodoAddViewModel.kt | 111 ++++++++++++++++++ 4 files changed, 205 insertions(+), 1 deletion(-) create mode 100644 app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt create mode 100644 app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt create mode 100644 app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddViewModel.kt diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt index ece31ecb..a3efd089 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt @@ -47,7 +47,7 @@ constructor( ) ) setSideEffect(TodoContract.TodoSideEffect.ShowSnackBar("${event.selectedFilterItem.filter}으로 정렬했어요")) - //TODO index를 이용해 서버로 FetchInfo 이름 보내주기 + //TODO index를 이용해 서버로 FetchInfo 보내주기 다시 정렬하기 ㅋㅋ } TodoContract.TodoEvent.OnFilterBottomSheetDismissRequest -> updateState( diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt new file mode 100644 index 00000000..e84fbeee --- /dev/null +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt @@ -0,0 +1,73 @@ +package org.android.bbangzip.presentation.ui.todo.todoadd + +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch + +@Composable +fun TodoAddRoute( + snackBarHostState: SnackbarHostState, + navigateToToDo: () -> Unit = {}, + navigateToBack: () -> Unit = {}, + viewModel: TodoAddViewModel = hiltViewModel() +) { + val todoAddState by viewModel.uiState.collectAsStateWithLifecycle() + val success by viewModel.success.collectAsStateWithLifecycle(initialValue = true) + + LaunchedEffect(viewModel.uiSideEffect) { + viewModel.uiSideEffect.collectLatest { effect -> + when (effect) { + TodoAddContract.TodoAddSideEffect.NavigateToBack -> + navigateToBack() + + TodoAddContract.TodoAddSideEffect.NavigateToToDo -> + navigateToToDo() + + is TodoAddContract.TodoAddSideEffect.ShowSnackBar -> { + val job = + launch { + snackBarHostState.currentSnackbarData?.dismiss() + snackBarHostState.showSnackbar(effect.message) + } + delay(2000) + job.cancel() + } + } + } + } + + when (success) { + true -> + TodoAddScreen( + todoAddState = todoAddState, + onBackIconClicked = { + viewModel.setEvent(TodoAddContract.TodoAddEvent.OnBackIconClicked) + }, + onFilterBottomSheetDismissRequest = { + viewModel.setEvent(TodoAddContract.TodoAddEvent.OnFilterIconClicked) + }, + nFilterIconClicked = { + viewModel.setEvent(TodoAddContract.TodoAddEvent.OnFilterBottomSheetDismissRequest) + }, + onFilterBottomSheetItemClicked = { filter -> + viewModel.setEvent(TodoAddContract.TodoAddEvent.OnFilterBottomSheetItemClicked(selectedFilterItem = filter)) + }, + onItemPlusButtonClicked = { + viewModel.setEvent(TodoAddContract.TodoAddEvent.OnItemPlusButtonClicked) + }, + onToDoCardClicked = { pieceId, cardState -> + viewModel.setEvent(TodoAddContract.TodoAddEvent.OnToDoCardClicked(pieceId = pieceId, cardState = cardState)) + } + ) + + false -> + Text("땡!") + } +} diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt new file mode 100644 index 00000000..dde3d44a --- /dev/null +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt @@ -0,0 +1,20 @@ +package org.android.bbangzip.presentation.ui.todo.todoadd + +import androidx.compose.runtime.Composable +import androidx.compose.ui.Modifier +import org.android.bbangzip.presentation.component.card.BbangZipCardState +import org.android.bbangzip.presentation.type.ToDoFilterType + +@Composable +fun TodoAddScreen( + todoAddState : TodoAddContract.TodoAddState, + modifier: Modifier = Modifier, + onBackIconClicked: () -> Unit, + onFilterBottomSheetDismissRequest: () -> Unit, + nFilterIconClicked: () -> Unit, + onFilterBottomSheetItemClicked: (ToDoFilterType) -> Unit, + onItemPlusButtonClicked: () -> Unit, + onToDoCardClicked: (Int, BbangZipCardState) -> Unit = { _, _ -> }, + ) { + +} \ No newline at end of file diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddViewModel.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddViewModel.kt new file mode 100644 index 00000000..792137b8 --- /dev/null +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddViewModel.kt @@ -0,0 +1,111 @@ +package org.android.bbangzip.presentation.ui.todo.todoadd + +import android.os.Parcelable +import androidx.lifecycle.SavedStateHandle +import dagger.hilt.android.lifecycle.HiltViewModel +import org.android.bbangzip.presentation.component.card.BbangZipCardState +import org.android.bbangzip.presentation.ui.todo.TodoContract +import org.android.bbangzip.presentation.util.base.BaseViewModel +import javax.inject.Inject + +@HiltViewModel +class TodoAddViewModel +@Inject +constructor( + savedStateHandle: SavedStateHandle, +) : BaseViewModel( + savedStateHandle = savedStateHandle, +) { + override fun createInitialState(savedState: Parcelable?): TodoAddContract.TodoAddState { + return savedState as? TodoAddContract.TodoAddState ?: TodoAddContract.TodoAddState() + } + + override fun handleEvent(event: TodoAddContract.TodoAddEvent) { + when (event) { + TodoAddContract.TodoAddEvent.Initialize -> TODO() + + TodoAddContract.TodoAddEvent.OnBackIconClicked -> { + updateState(TodoAddContract.TodoAddReduce.ResetSelectedItemList) + setSideEffect(TodoAddContract.TodoAddSideEffect.NavigateToBack) + } + + TodoAddContract.TodoAddEvent.OnFilterBottomSheetDismissRequest -> updateState( + TodoAddContract.TodoAddReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = false + ) + ) + + TodoAddContract.TodoAddEvent.OnFilterIconClicked -> updateState( + TodoAddContract.TodoAddReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = false + ) + ) + + is TodoAddContract.TodoAddEvent.OnFilterBottomSheetItemClicked -> { + updateState(TodoAddContract.TodoAddReduce.UpdateFilterType(selectedFilter = event.selectedFilterItem)) + updateState( + TodoAddContract.TodoAddReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = false + ) + ) + setSideEffect(TodoAddContract.TodoAddSideEffect.ShowSnackBar("${event.selectedFilterItem.filter}으로 정렬했어요")) + //TODO 받아오고 다시 정렬해야됨 ㅋㅋ + } + + TodoAddContract.TodoAddEvent.OnItemPlusButtonClicked -> { + // TODO 서버로 보내기 + setSideEffect(TodoAddContract.TodoAddSideEffect.NavigateToToDo) + } + + is TodoAddContract.TodoAddEvent.OnToDoCardClicked -> { + if (event.cardState == BbangZipCardState.CHECKED) { + updateState(TodoAddContract.TodoAddReduce.UpdateSelectedItemList(pieceId = event.pieceId)) + updateState( + TodoAddContract.TodoAddReduce.UpdateCardState( + pieceId = event.pieceId, + cardState = event.cardState + ) + ) + } else { + updateState(TodoAddContract.TodoAddReduce.DeleteSelectedItemList(pieceId = event.pieceId)) + updateState( + TodoAddContract.TodoAddReduce.UpdateCardState( + pieceId = event.pieceId, + cardState = event.cardState + ) + ) + } + } + } + } + + override fun reduceState(state: TodoAddContract.TodoAddState, reduce: TodoAddContract.TodoAddReduce): TodoAddContract.TodoAddState { + return when (reduce) { + TodoAddContract.TodoAddReduce.ResetSelectedItemList -> state.copy( + selectedItemList = listOf() + ) + + is TodoAddContract.TodoAddReduce.UpdateCardState -> state.copy( + todoList = state.todoList.map { item -> + if (item.pieceId == reduce.pieceId) item.copy(cardState = reduce.cardState) else item + } + ) + + is TodoAddContract.TodoAddReduce.UpdateFilterType -> state.copy( + selectedFilter = reduce.selectedFilter + ) + + is TodoAddContract.TodoAddReduce.UpdateSelectedItemList -> state.copy( + selectedItemList = state.selectedItemList.plus(reduce.pieceId) + ) + + is TodoAddContract.TodoAddReduce.UpdateToDoFilterBottomSheetState -> state.copy( + todoFilterBottomSheetState = reduce.todoFilterBottomSheetState + ) + + is TodoAddContract.TodoAddReduce.DeleteSelectedItemList -> state.copy( + selectedItemList = state.selectedItemList.minus(reduce.pieceId) + ) + } + } +} \ No newline at end of file From 50e898c8aaa15b0b45c720257a815296e49196d7 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sun, 19 Jan 2025 16:47:34 +0900 Subject: [PATCH 27/40] =?UTF-8?q?[feat]=20#31=20ToDoAddScreen=20=EA=B5=AC?= =?UTF-8?q?=ED=98=84?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/ui/navigator/MainNavHost.kt | 2 +- .../ui/navigator/MainNavigator.kt | 11 -- .../presentation/ui/todo/TodoScreen.kt | 2 +- .../ui/todo/todoadd/TodoAddContract.kt | 115 ++++++++++++- .../ui/todo/todoadd/TodoAddRoute.kt | 20 ++- .../ui/todo/todoadd/TodoAddScreen.kt | 151 +++++++++++++++++- .../ui/todo/todoadd/TodoAddViewModel.kt | 5 +- app/src/main/res/values/strings.xml | 6 + 8 files changed, 291 insertions(+), 21 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt index 52428c2b..39aa94cc 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt @@ -47,7 +47,7 @@ fun MainNavHost( todoAddNavGraph( snackBarHostState = snackBarHostState, navigateToBack = { navigator.popBackStackIfNotSubject() }, - navigateToToDo = { navigator.navigateToToDo() } + navigateToToDo = { navigator.popBackStackIfNotSubject() } ) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt index a996d0be..d4a27aae 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt @@ -63,17 +63,6 @@ class MainNavigator( navHostController.navigateLogin() } - fun navigateToToDo() { - navHostController.navigateTodo(navOptions { - popUpTo(BottomNavigationRoute.Subject::class.qualifiedName.orEmpty()) { - saveState = true - Timber.d("[navigation] restoreState -> $saveState") - } - launchSingleTop = true - restoreState = true - }) - } - fun navigateToToDoAdd() { navHostController.navigateTodoAdd() } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt index d7072cdb..e34a0284 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt @@ -66,7 +66,7 @@ fun TodoScreen( onDefaultScreenCardClicked: (Int, BbangZipCardState) -> Unit = { _, _ -> }, ) { Box( - modifier = modifier + modifier = modifier .fillMaxSize() .padding(bottom = 74.dp) .background(color = BbangZipTheme.colors.staticWhite_FFFFFF) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddContract.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddContract.kt index 10028392..23626783 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddContract.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddContract.kt @@ -10,7 +10,118 @@ import org.android.bbangzip.presentation.util.base.BaseContract class TodoAddContract { @Parcelize data class TodoAddState( - val todoList: List = listOf(), + val todoList: List = listOf( + ToDoCardModel( + pieceId = 1, + subjectName = "Math", + examName = "Algebra Exam", + studyContents = "Review Chapters 1-3", + startPage = 1, + finishPage = 50, + deadline = "2025-01-20", + remainingDays = 2, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 2, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = -3, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 3, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 7, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 4, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Checkable abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = -2, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 5, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = 4, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 6, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = -1, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 7, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Checkable abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = 5, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 8, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = -4, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 9, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 3, + cardState = BbangZipCardState.DEFAULT + ), + ToDoCardModel( + pieceId = 10, + subjectName = "Art", + examName = "Painting Project", + studyContents = "CHECKABLE abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = -5, + cardState = BbangZipCardState.CHECKABLE + ) + ), val todoFilterBottomSheetState: Boolean = false, val selectedFilter: ToDoFilterType = ToDoFilterType.RECENT, val selectedItemList: List = listOf(), @@ -65,5 +176,7 @@ class TodoAddContract { data object NavigateToBack : TodoAddSideEffect data class ShowSnackBar(val message: String) : TodoAddSideEffect + + data class ShowTodoAddSnackBar(val message: String) : TodoAddSideEffect } } \ No newline at end of file diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt index e84fbeee..35f0127e 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt @@ -1,10 +1,12 @@ package org.android.bbangzip.presentation.ui.todo.todoadd +import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember import androidx.hilt.navigation.compose.hiltViewModel import androidx.lifecycle.compose.collectAsStateWithLifecycle import kotlinx.coroutines.delay @@ -20,6 +22,7 @@ fun TodoAddRoute( ) { val todoAddState by viewModel.uiState.collectAsStateWithLifecycle() val success by viewModel.success.collectAsStateWithLifecycle(initialValue = true) + val todoAddsSnackBarHostState = remember { SnackbarHostState() } LaunchedEffect(viewModel.uiSideEffect) { viewModel.uiSideEffect.collectLatest { effect -> @@ -39,6 +42,16 @@ fun TodoAddRoute( delay(2000) job.cancel() } + + is TodoAddContract.TodoAddSideEffect.ShowTodoAddSnackBar -> { + val job = + launch { + todoAddsSnackBarHostState.currentSnackbarData?.dismiss() + todoAddsSnackBarHostState.showSnackbar(effect.message) + } + delay(2000) + job.cancel() + } } } } @@ -47,15 +60,16 @@ fun TodoAddRoute( true -> TodoAddScreen( todoAddState = todoAddState, + todoAddSnackBarHostState = todoAddsSnackBarHostState, onBackIconClicked = { viewModel.setEvent(TodoAddContract.TodoAddEvent.OnBackIconClicked) }, onFilterBottomSheetDismissRequest = { - viewModel.setEvent(TodoAddContract.TodoAddEvent.OnFilterIconClicked) - }, - nFilterIconClicked = { viewModel.setEvent(TodoAddContract.TodoAddEvent.OnFilterBottomSheetDismissRequest) }, + onFilterIconClicked = { + viewModel.setEvent(TodoAddContract.TodoAddEvent.OnFilterIconClicked) + }, onFilterBottomSheetItemClicked = { filter -> viewModel.setEvent(TodoAddContract.TodoAddEvent.OnFilterBottomSheetItemClicked(selectedFilterItem = filter)) }, diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt index dde3d44a..7aaafddf 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt @@ -1,20 +1,167 @@ package org.android.bbangzip.presentation.ui.todo.todoadd +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +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.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Icon +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.unit.dp +import org.android.bbangzip.R +import org.android.bbangzip.presentation.component.button.BbangZipButton import org.android.bbangzip.presentation.component.card.BbangZipCardState +import org.android.bbangzip.presentation.component.card.ToDoCard +import org.android.bbangzip.presentation.component.snackbar.BbangZipSnackBarHost +import org.android.bbangzip.presentation.component.topbar.BbangZipBaseTopBar +import org.android.bbangzip.presentation.type.BbangZipButtonSize +import org.android.bbangzip.presentation.type.BbangZipButtonType import org.android.bbangzip.presentation.type.ToDoFilterType +import org.android.bbangzip.presentation.ui.todo.BbangZipToDoFilterPickerBottomSheet +import org.android.bbangzip.ui.theme.BbangZipTheme @Composable fun TodoAddScreen( - todoAddState : TodoAddContract.TodoAddState, + todoAddState: TodoAddContract.TodoAddState, + todoAddSnackBarHostState: SnackbarHostState, modifier: Modifier = Modifier, onBackIconClicked: () -> Unit, onFilterBottomSheetDismissRequest: () -> Unit, - nFilterIconClicked: () -> Unit, + onFilterIconClicked: () -> Unit, onFilterBottomSheetItemClicked: (ToDoFilterType) -> Unit, onItemPlusButtonClicked: () -> Unit, onToDoCardClicked: (Int, BbangZipCardState) -> Unit = { _, _ -> }, +) { + Box( + modifier = modifier + .fillMaxSize() + .background(color = BbangZipTheme.colors.staticWhite_FFFFFF) ) { + Column { + val scrollState = rememberLazyListState() + val isShadowed by remember { + derivedStateOf { + scrollState.firstVisibleItemScrollOffset > 0 + } + } + BbangZipBaseTopBar( + isShadowed = isShadowed, + title = "", + leadingIcon = R.drawable.ic_chevronleft_thick_small_24, + onLeadingIconClick = onBackIconClicked + ) + LazyColumn( + modifier = Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), + state = scrollState + ) { + item { + Text(text = stringResource(R.string.todo_add_title1), style = BbangZipTheme.typography.body1Bold, color = BbangZipTheme.colors.labelAlternative_282119_61) + + Spacer(modifier = Modifier.height(8.dp)) + + Text(text = stringResource(R.string.todo_add_title2), style = BbangZipTheme.typography.title3Bold, color = BbangZipTheme.colors.labelNormal_282119) + + Spacer(modifier = Modifier.height(32.dp)) + } + + item { + Row { + Spacer(modifier = Modifier.width(8.dp)) + + + Text(text = "${todoAddState.selectedItemList.size} ", style = BbangZipTheme.typography.body2Bold, color = BbangZipTheme.colors.labelNormal_282119) + Text(text = stringResource(R.string.todo_add_count, todoAddState.todoList.size), style = BbangZipTheme.typography.body2Bold, color = BbangZipTheme.colors.labelAlternative_282119_61) + + Spacer(modifier = Modifier.weight(1f)) + + Box( + modifier = Modifier + .clip(CircleShape) + .clickable { onFilterIconClicked() }, contentAlignment = Alignment.Center + ) { + Icon( + imageVector = ImageVector.vectorResource(R.drawable.ic_filter_default_24), + contentDescription = null, + modifier = Modifier.padding(8.dp), + tint = BbangZipTheme.colors.labelAlternative_282119_61 + + ) + } + } + } + + items( + count = todoAddState.todoList.size, + key = { index -> + todoAddState.todoList[index].pieceId + }) { index -> + ToDoCard( + data = todoAddState.todoList[index], + modifier = Modifier.padding(horizontal = 16.dp, vertical = 6.dp), + onClick = { + if (todoAddState.todoList[index].cardState == BbangZipCardState.CHECKED) + onToDoCardClicked( + todoAddState.todoList[index].pieceId, + BbangZipCardState.CHECKABLE + ) + else (todoAddState.todoList[index].cardState == BbangZipCardState.CHECKABLE) + onToDoCardClicked( + todoAddState.todoList[index].pieceId, + BbangZipCardState.CHECKED + ) + + } + ) + } + } + } + Column( + modifier = Modifier.align(Alignment.BottomCenter), + horizontalAlignment = Alignment.CenterHorizontally + ) { + BbangZipSnackBarHost(snackBarHostState = todoAddSnackBarHostState) + + BbangZipButton( + bbangZipButtonType = BbangZipButtonType.Solid, + bbangZipButtonSize = BbangZipButtonSize.Large, + onClick = { onItemPlusButtonClicked() }, + label = stringResource(R.string.todo_add_plus_button_label), + modifier = Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth() + .padding(bottom = 16.dp), + isEnable = todoAddState.selectedItemList.isNotEmpty(), + trailingIcon = R.drawable.ic_plus_thick_24, + ) + } + } + BbangZipToDoFilterPickerBottomSheet( + isBottomSheetVisible = todoAddState.todoFilterBottomSheetState, + selectedItem = todoAddState.selectedFilter, + onSelectedItemChanged = onFilterBottomSheetItemClicked, + onDismissRequest = onFilterBottomSheetDismissRequest + ) } \ No newline at end of file diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddViewModel.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddViewModel.kt index 792137b8..4ea4a395 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddViewModel.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddViewModel.kt @@ -37,7 +37,7 @@ constructor( TodoAddContract.TodoAddEvent.OnFilterIconClicked -> updateState( TodoAddContract.TodoAddReduce.UpdateToDoFilterBottomSheetState( - todoFilterBottomSheetState = false + todoFilterBottomSheetState = true ) ) @@ -48,13 +48,14 @@ constructor( todoFilterBottomSheetState = false ) ) - setSideEffect(TodoAddContract.TodoAddSideEffect.ShowSnackBar("${event.selectedFilterItem.filter}으로 정렬했어요")) + setSideEffect(TodoAddContract.TodoAddSideEffect.ShowTodoAddSnackBar("${event.selectedFilterItem.filter}으로 정렬했어요")) //TODO 받아오고 다시 정렬해야됨 ㅋㅋ } TodoAddContract.TodoAddEvent.OnItemPlusButtonClicked -> { // TODO 서버로 보내기 setSideEffect(TodoAddContract.TodoAddSideEffect.NavigateToToDo) + setSideEffect(TodoAddContract.TodoAddSideEffect.ShowSnackBar("오늘 할 공부를 추가했어요!")) } is TodoAddContract.TodoAddEvent.OnToDoCardClicked -> { diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index a74067a3..cb9be13d 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -88,4 +88,10 @@ 제 과제 빵점 사장님은\n이번 학기 백점! 5초 만에 빵집 사장님 되기 되돌리기 + 이제는 미룰 수 없다! + 아직 늦지 않았어요!\n밀린 공부를 시작해봐요 + 시작이 빵이다! + 오늘부터 하나씩!\n공부할 내용을 선택해 보세요 + 개 / 총 %s개 + 오늘 할 공부 추가하기 \ No newline at end of file From ff58dfd06737830fddff55f0eb74e941b0e36fd5 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sun, 19 Jan 2025 17:15:16 +0900 Subject: [PATCH 28/40] =?UTF-8?q?[feat]=20#31=20TodoAddPending=20Screen=20?= =?UTF-8?q?navigaion=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/ui/navigator/MainNavHost.kt | 8 ++++- .../ui/navigator/MainNavigator.kt | 5 +++ .../navigation/TodoAddPendingNavigation.kt | 31 +++++++++++++++++++ app/src/main/res/values/strings.xml | 2 +- 4 files changed, 44 insertions(+), 2 deletions(-) create mode 100644 app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/navigation/TodoAddPendingNavigation.kt diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt index 39aa94cc..a87de4cb 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt @@ -16,6 +16,7 @@ import org.android.bbangzip.presentation.ui.subject.navigateSubject import org.android.bbangzip.presentation.ui.subject.subjectNavGraph import org.android.bbangzip.presentation.ui.todo.navigation.todoNavGraph import org.android.bbangzip.presentation.ui.todo.todoadd.navigation.todoAddNavGraph +import org.android.bbangzip.presentation.ui.todo.pendingtodoadd.navigation.todoAddPendingNavGraph import org.android.bbangzip.ui.theme.BbangZipTheme @Composable @@ -50,6 +51,11 @@ fun MainNavHost( navigateToToDo = { navigator.popBackStackIfNotSubject() } ) + todoAddPendingNavGraph( + snackBarHostState = snackBarHostState, + navigateToBack = { navigator.popBackStackIfNotSubject() }, + navigateToToDo = { navigator.popBackStackIfNotSubject() } + ) friendNavGraph() @@ -60,7 +66,7 @@ fun MainNavHost( todoNavGraph( snackBarHostState = snackBarHostState, navigateToAddToDo = { navigator.navigateToToDoAdd() }, - navigateToAddPendingToDo = {}, + navigateToAddPendingToDo = {navigator.navigateToToDoAddPending()}, ) } } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt index d4a27aae..e482d319 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt @@ -17,6 +17,7 @@ import org.android.bbangzip.presentation.ui.login.navigateLogin import org.android.bbangzip.presentation.ui.my.navigateMy import org.android.bbangzip.presentation.ui.subject.navigateSubject import org.android.bbangzip.presentation.ui.todo.navigation.navigateTodo +import org.android.bbangzip.presentation.ui.todo.pendingtodoadd.navigation.navigateTodoAddPending import org.android.bbangzip.presentation.ui.todo.todoadd.navigation.navigateTodoAdd import timber.log.Timber @@ -67,6 +68,10 @@ class MainNavigator( navHostController.navigateTodoAdd() } + fun navigateToToDoAddPending() { + navHostController.navigateTodoAddPending() + } + private fun popBackStack() { navHostController.popBackStack() } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/navigation/TodoAddPendingNavigation.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/navigation/TodoAddPendingNavigation.kt new file mode 100644 index 00000000..cdcb4aae --- /dev/null +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/navigation/TodoAddPendingNavigation.kt @@ -0,0 +1,31 @@ +package org.android.bbangzip.presentation.ui.todo.pendingtodoadd.navigation + +import androidx.compose.material3.SnackbarHostState +import androidx.navigation.NavController +import androidx.navigation.NavGraphBuilder +import androidx.navigation.compose.composable +import kotlinx.serialization.Serializable +import org.android.bbangzip.presentation.ui.todo.pendingtodoadd.TodoAddPendingRoute + +@Serializable +object TodoAddPendingRoute + +fun NavController.navigateTodoAddPending() { + navigate( + route = TodoAddPendingRoute, + ) +} + +fun NavGraphBuilder.todoAddPendingNavGraph( + snackBarHostState: SnackbarHostState, + navigateToToDo: () -> Unit, + navigateToBack: () -> Unit, +) { + composable { + TodoAddPendingRoute( + snackBarHostState = snackBarHostState, + navigateToToDo = navigateToToDo, + navigateToBack = navigateToBack, + ) + } +} \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index cb9be13d..ccff04bf 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -89,7 +89,7 @@ 5초 만에 빵집 사장님 되기 되돌리기 이제는 미룰 수 없다! - 아직 늦지 않았어요!\n밀린 공부를 시작해봐요 + 아직 늦지 않았어요!\n밀린 공부를 시작해봐요 시작이 빵이다! 오늘부터 하나씩!\n공부할 내용을 선택해 보세요 개 / 총 %s개 From 5619d1e5c3c000ec46e4e2ec24dae643e2402733 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sun, 19 Jan 2025 17:18:04 +0900 Subject: [PATCH 29/40] =?UTF-8?q?[feat]=20#31=20TodoAdd=20->=20TodoAddPend?= =?UTF-8?q?ing=20=EC=97=B0=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../ui/todo/navigation/TodoNavigation.kt | 3 +- .../ui/todo/todoadd/TodoAddRoute.kt | 3 +- .../ui/todo/todoadd/TodoAddScreen.kt | 40 +++++++++++++++---- .../ui/todo/todoadd/TodoAddViewModel.kt | 1 - 4 files changed, 36 insertions(+), 11 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt index 933484ad..c96f215d 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt @@ -23,7 +23,8 @@ fun NavGraphBuilder.todoNavGraph( composable { TodoRoute( snackBarHostState = snackBarHostState, - navigateToAddToDo = navigateToAddToDo + navigateToAddToDo = navigateToAddToDo, + navigateToAddPendingToDo = navigateToAddPendingToDo ) } } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt index 35f0127e..ea0fb965 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt @@ -1,6 +1,5 @@ package org.android.bbangzip.presentation.ui.todo.todoadd -import androidx.compose.material3.SnackbarHost import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -49,7 +48,7 @@ fun TodoAddRoute( todoAddsSnackBarHostState.currentSnackbarData?.dismiss() todoAddsSnackBarHostState.showSnackbar(effect.message) } - delay(2000) + delay(3000) job.cancel() } } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt index 7aaafddf..66916dbd 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt @@ -71,6 +71,8 @@ fun TodoAddScreen( onLeadingIconClick = onBackIconClicked ) + Spacer(modifier = Modifier.height(32.dp)) + LazyColumn( modifier = Modifier .padding(horizontal = 16.dp) @@ -78,29 +80,51 @@ fun TodoAddScreen( state = scrollState ) { item { - Text(text = stringResource(R.string.todo_add_title1), style = BbangZipTheme.typography.body1Bold, color = BbangZipTheme.colors.labelAlternative_282119_61) + Text( + text = stringResource(R.string.todo_add_title1), + style = BbangZipTheme.typography.body1Bold, + color = BbangZipTheme.colors.labelAlternative_282119_61 + ) Spacer(modifier = Modifier.height(8.dp)) - Text(text = stringResource(R.string.todo_add_title2), style = BbangZipTheme.typography.title3Bold, color = BbangZipTheme.colors.labelNormal_282119) + Text( + text = stringResource(R.string.todo_add_title2), + style = BbangZipTheme.typography.title3Bold, + color = BbangZipTheme.colors.labelNormal_282119 + ) Spacer(modifier = Modifier.height(32.dp)) } item { - Row { + Row( + verticalAlignment = Alignment.CenterVertically + ) { Spacer(modifier = Modifier.width(8.dp)) - Text(text = "${todoAddState.selectedItemList.size} ", style = BbangZipTheme.typography.body2Bold, color = BbangZipTheme.colors.labelNormal_282119) - Text(text = stringResource(R.string.todo_add_count, todoAddState.todoList.size), style = BbangZipTheme.typography.body2Bold, color = BbangZipTheme.colors.labelAlternative_282119_61) + Text( + text = "${todoAddState.selectedItemList.size} ", + style = BbangZipTheme.typography.body2Bold, + color = BbangZipTheme.colors.labelNormal_282119 + ) + Text( + text = stringResource( + R.string.todo_add_count, + todoAddState.todoList.size + ), + style = BbangZipTheme.typography.body2Bold, + color = BbangZipTheme.colors.labelAlternative_282119_61 + ) Spacer(modifier = Modifier.weight(1f)) Box( modifier = Modifier .clip(CircleShape) - .clickable { onFilterIconClicked() }, contentAlignment = Alignment.Center + .clickable { onFilterIconClicked() }, + contentAlignment = Alignment.Center ) { Icon( imageVector = ImageVector.vectorResource(R.drawable.ic_filter_default_24), @@ -111,6 +135,8 @@ fun TodoAddScreen( ) } } + + Spacer(modifier = Modifier.height(18.dp)) } items( @@ -120,7 +146,7 @@ fun TodoAddScreen( }) { index -> ToDoCard( data = todoAddState.todoList[index], - modifier = Modifier.padding(horizontal = 16.dp, vertical = 6.dp), + modifier = Modifier.padding( vertical = 6.dp), onClick = { if (todoAddState.todoList[index].cardState == BbangZipCardState.CHECKED) onToDoCardClicked( diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddViewModel.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddViewModel.kt index 4ea4a395..2689095b 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddViewModel.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddViewModel.kt @@ -4,7 +4,6 @@ import android.os.Parcelable import androidx.lifecycle.SavedStateHandle import dagger.hilt.android.lifecycle.HiltViewModel import org.android.bbangzip.presentation.component.card.BbangZipCardState -import org.android.bbangzip.presentation.ui.todo.TodoContract import org.android.bbangzip.presentation.util.base.BaseViewModel import javax.inject.Inject From 3b475a859cf5c722dc7ea2fdc7dec83931680ae0 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sun, 19 Jan 2025 17:18:19 +0900 Subject: [PATCH 30/40] =?UTF-8?q?[feat]=20#31=20pendingscreen=20=EC=97=B0?= =?UTF-8?q?=EA=B2=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../pendingtodoadd/TodoAddPendingContract.kt | 182 ++++++++++++++++++ .../pendingtodoadd/TodoAddPendingRoute.kt | 86 +++++++++ .../pendingtodoadd/TodoAddPendingScreen.kt | 173 +++++++++++++++++ .../pendingtodoadd/TodoAddPendingViewModel.kt | 111 +++++++++++ 4 files changed, 552 insertions(+) create mode 100644 app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingContract.kt create mode 100644 app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingRoute.kt create mode 100644 app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt create mode 100644 app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingViewModel.kt diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingContract.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingContract.kt new file mode 100644 index 00000000..30e1a539 --- /dev/null +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingContract.kt @@ -0,0 +1,182 @@ +package org.android.bbangzip.presentation.ui.todo.pendingtodoadd + +import android.os.Parcelable +import kotlinx.parcelize.Parcelize +import org.android.bbangzip.presentation.component.card.BbangZipCardState +import org.android.bbangzip.presentation.model.card.ToDoCardModel +import org.android.bbangzip.presentation.type.ToDoFilterType +import org.android.bbangzip.presentation.util.base.BaseContract + +class TodoAddPendingContract { + @Parcelize + data class TodoAddPendingState( + val todoList: List = listOf( + ToDoCardModel( + pieceId = 1, + subjectName = "Math", + examName = "Algebra Exam", + studyContents = "Review Chapters 1-3", + startPage = 1, + finishPage = 50, + deadline = "2025-01-20", + remainingDays = 2, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 2, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = -3, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 3, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 7, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 4, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Checkable abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = -2, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 5, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = 4, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 6, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = -1, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 7, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Checkable abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = 5, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 8, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = -4, + cardState = BbangZipCardState.CHECKABLE + ), + ToDoCardModel( + pieceId = 9, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 3, + cardState = BbangZipCardState.DEFAULT + ), + ToDoCardModel( + pieceId = 10, + subjectName = "Art", + examName = "Painting Project", + studyContents = "CHECKABLE abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = -5, + cardState = BbangZipCardState.CHECKABLE + ) + ), + val todoFilterBottomSheetState: Boolean = false, + val selectedFilter: ToDoFilterType = ToDoFilterType.RECENT, + val selectedItemList: List = listOf(), + ) : BaseContract.State, Parcelable { + override fun toParcelable(): Parcelable = this + } + + sealed interface TodoAddPendingEvent : BaseContract.Event { + data object Initialize : TodoAddPendingEvent + + data object OnFilterIconClicked : TodoAddPendingEvent + + data object OnBackIconClicked : TodoAddPendingEvent + + data object OnFilterBottomSheetDismissRequest : TodoAddPendingEvent + + data object OnItemPlusButtonClicked : TodoAddPendingEvent + + data class OnFilterBottomSheetItemClicked(val selectedFilterItem: ToDoFilterType) : TodoAddPendingEvent + + data class OnToDoCardClicked(val pieceId: Int, val cardState: BbangZipCardState) : TodoAddPendingEvent + } + + sealed interface TodoAddPendingReduce : BaseContract.Reduce { + data object ResetSelectedItemList : TodoAddPendingReduce + + data class UpdateSelectedItemList( + val pieceId: Int + ) : TodoAddPendingReduce + + data class UpdateToDoFilterBottomSheetState( + val todoFilterBottomSheetState: Boolean + ) : TodoAddPendingReduce + + data class UpdateFilterType( + val selectedFilter: ToDoFilterType + ) : TodoAddPendingReduce + + data class DeleteSelectedItemList( + val pieceId: Int + ) : TodoAddPendingReduce + + data class UpdateCardState( + val pieceId: Int, + val cardState: BbangZipCardState + ) : TodoAddPendingReduce + } + + sealed interface TodoAddPendingSideEffect : BaseContract.SideEffect { + data object NavigateToToDo : TodoAddPendingSideEffect + + data object NavigateToBack : TodoAddPendingSideEffect + + data class ShowSnackBar(val message: String) : TodoAddPendingSideEffect + + data class ShowTodoAddSnackBar(val message: String) : TodoAddPendingSideEffect + } +} \ No newline at end of file diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingRoute.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingRoute.kt new file mode 100644 index 00000000..059e57c5 --- /dev/null +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingRoute.kt @@ -0,0 +1,86 @@ +package org.android.bbangzip.presentation.ui.todo.pendingtodoadd + +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.LaunchedEffect +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.hilt.navigation.compose.hiltViewModel +import androidx.lifecycle.compose.collectAsStateWithLifecycle +import kotlinx.coroutines.delay +import kotlinx.coroutines.flow.collectLatest +import kotlinx.coroutines.launch + +@Composable +fun TodoAddPendingRoute( + snackBarHostState: SnackbarHostState, + navigateToToDo: () -> Unit = {}, + navigateToBack: () -> Unit = {}, + viewModel: TodoAddPendingViewModel = hiltViewModel() +) { + val todoAddPendingState by viewModel.uiState.collectAsStateWithLifecycle() + val success by viewModel.success.collectAsStateWithLifecycle(initialValue = true) + val todoAddsSnackBarHostState = remember { SnackbarHostState() } + + LaunchedEffect(viewModel.uiSideEffect) { + viewModel.uiSideEffect.collectLatest { effect -> + when (effect) { + TodoAddPendingContract.TodoAddPendingSideEffect.NavigateToBack -> + navigateToBack() + + TodoAddPendingContract.TodoAddPendingSideEffect.NavigateToToDo -> + navigateToToDo() + + is TodoAddPendingContract.TodoAddPendingSideEffect.ShowSnackBar -> { + val job = + launch { + snackBarHostState.currentSnackbarData?.dismiss() + snackBarHostState.showSnackbar(effect.message) + } + delay(2000) + job.cancel() + } + + is TodoAddPendingContract.TodoAddPendingSideEffect.ShowTodoAddSnackBar -> { + val job = + launch { + todoAddsSnackBarHostState.currentSnackbarData?.dismiss() + todoAddsSnackBarHostState.showSnackbar(effect.message) + } + delay(3000) + job.cancel() + } + } + } + } + + when (success) { + true -> + TodoAddPendingScreen( + todoAddState = todoAddPendingState, + todoAddSnackBarHostState = todoAddsSnackBarHostState, + onBackIconClicked = { + viewModel.setEvent(TodoAddPendingContract.TodoAddPendingEvent.OnBackIconClicked) + }, + onFilterBottomSheetDismissRequest = { + viewModel.setEvent(TodoAddPendingContract.TodoAddPendingEvent.OnFilterBottomSheetDismissRequest) + }, + onFilterIconClicked = { + viewModel.setEvent(TodoAddPendingContract.TodoAddPendingEvent.OnFilterIconClicked) + }, + onFilterBottomSheetItemClicked = { filter -> + viewModel.setEvent(TodoAddPendingContract.TodoAddPendingEvent.OnFilterBottomSheetItemClicked(selectedFilterItem = filter)) + }, + onItemPlusButtonClicked = { + viewModel.setEvent(TodoAddPendingContract.TodoAddPendingEvent.OnItemPlusButtonClicked) + }, + onToDoCardClicked = { pieceId, cardState -> + viewModel.setEvent(TodoAddPendingContract.TodoAddPendingEvent.OnToDoCardClicked(pieceId = pieceId, cardState = cardState)) + } + ) + + false -> + Text("땡!") + } +} diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt new file mode 100644 index 00000000..6eff35c9 --- /dev/null +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt @@ -0,0 +1,173 @@ +package org.android.bbangzip.presentation.ui.todo.pendingtodoadd + +import androidx.compose.foundation.background +import androidx.compose.foundation.clickable +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.width +import androidx.compose.foundation.lazy.LazyColumn +import androidx.compose.foundation.lazy.rememberLazyListState +import androidx.compose.foundation.shape.CircleShape +import androidx.compose.material3.Icon +import androidx.compose.material3.SnackbarHostState +import androidx.compose.material3.Text +import androidx.compose.runtime.Composable +import androidx.compose.runtime.derivedStateOf +import androidx.compose.runtime.getValue +import androidx.compose.runtime.remember +import androidx.compose.ui.Alignment +import androidx.compose.ui.Modifier +import androidx.compose.ui.draw.clip +import androidx.compose.ui.graphics.vector.ImageVector +import androidx.compose.ui.res.stringResource +import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.unit.dp +import org.android.bbangzip.R +import org.android.bbangzip.presentation.component.button.BbangZipButton +import org.android.bbangzip.presentation.component.card.BbangZipCardState +import org.android.bbangzip.presentation.component.card.ToDoCard +import org.android.bbangzip.presentation.component.snackbar.BbangZipSnackBarHost +import org.android.bbangzip.presentation.component.topbar.BbangZipBaseTopBar +import org.android.bbangzip.presentation.type.BbangZipButtonSize +import org.android.bbangzip.presentation.type.BbangZipButtonType +import org.android.bbangzip.presentation.type.ToDoFilterType +import org.android.bbangzip.presentation.ui.todo.BbangZipToDoFilterPickerBottomSheet +import org.android.bbangzip.ui.theme.BbangZipTheme + +@Composable +fun TodoAddPendingScreen( + todoAddState: TodoAddPendingContract.TodoAddPendingState, + todoAddSnackBarHostState: SnackbarHostState, + modifier: Modifier = Modifier, + onBackIconClicked: () -> Unit, + onFilterBottomSheetDismissRequest: () -> Unit, + onFilterIconClicked: () -> Unit, + onFilterBottomSheetItemClicked: (ToDoFilterType) -> Unit, + onItemPlusButtonClicked: () -> Unit, + onToDoCardClicked: (Int, BbangZipCardState) -> Unit = { _, _ -> }, +) { + Box( + modifier = modifier + .fillMaxSize() + .background(color = BbangZipTheme.colors.staticWhite_FFFFFF) + ) { + Column { + val scrollState = rememberLazyListState() + val isShadowed by remember { + derivedStateOf { + scrollState.firstVisibleItemScrollOffset > 0 + } + } + BbangZipBaseTopBar( + isShadowed = isShadowed, + title = "", + leadingIcon = R.drawable.ic_chevronleft_thick_small_24, + onLeadingIconClick = onBackIconClicked + ) + + Spacer(modifier = Modifier.height(32.dp)) + + LazyColumn( + modifier = Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), + state = scrollState + ) { + item { + Text(text = stringResource(R.string.todo_pending_add_title1), style = BbangZipTheme.typography.body1Bold, color = BbangZipTheme.colors.labelAlternative_282119_61) + + Spacer(modifier = Modifier.height(8.dp)) + + Text(text = stringResource(R.string.todo_pending_add_title2), style = BbangZipTheme.typography.title3Bold, color = BbangZipTheme.colors.labelNormal_282119) + + Spacer(modifier = Modifier.height(32.dp)) + } + + item { + Row( + verticalAlignment = Alignment.CenterVertically + ) { + Spacer(modifier = Modifier.width(8.dp)) + + + Text(text = "${todoAddState.selectedItemList.size} ", style = BbangZipTheme.typography.body2Bold, color = BbangZipTheme.colors.labelNormal_282119) + Text(text = stringResource(R.string.todo_add_count, todoAddState.todoList.size), style = BbangZipTheme.typography.body2Bold, color = BbangZipTheme.colors.labelAlternative_282119_61) + + Spacer(modifier = Modifier.weight(1f)) + + Box( + modifier = Modifier + .clip(CircleShape) + .clickable { onFilterIconClicked() }, contentAlignment = Alignment.Center + ) { + Icon( + imageVector = ImageVector.vectorResource(R.drawable.ic_filter_default_24), + contentDescription = null, + modifier = Modifier.padding(8.dp), + tint = BbangZipTheme.colors.labelAlternative_282119_61 + + ) + } + } + + Spacer(modifier = Modifier.height(18.dp)) + } + + items( + count = todoAddState.todoList.size, + key = { index -> + todoAddState.todoList[index].pieceId + }) { index -> + ToDoCard( + data = todoAddState.todoList[index], + modifier = Modifier.padding(vertical = 6.dp), + onClick = { + if (todoAddState.todoList[index].cardState == BbangZipCardState.CHECKED) + onToDoCardClicked( + todoAddState.todoList[index].pieceId, + BbangZipCardState.CHECKABLE + ) + else (todoAddState.todoList[index].cardState == BbangZipCardState.CHECKABLE) + onToDoCardClicked( + todoAddState.todoList[index].pieceId, + BbangZipCardState.CHECKED + ) + + } + ) + } + } + } + Column( + modifier = Modifier.align(Alignment.BottomCenter), + horizontalAlignment = Alignment.CenterHorizontally + ) { + BbangZipSnackBarHost(snackBarHostState = todoAddSnackBarHostState) + + BbangZipButton( + bbangZipButtonType = BbangZipButtonType.Solid, + bbangZipButtonSize = BbangZipButtonSize.Large, + onClick = { onItemPlusButtonClicked() }, + label = stringResource(R.string.todo_add_plus_button_label), + modifier = Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth() + .padding(bottom = 16.dp), + isEnable = todoAddState.selectedItemList.isNotEmpty(), + trailingIcon = R.drawable.ic_plus_thick_24, + ) + } + } + BbangZipToDoFilterPickerBottomSheet( + isBottomSheetVisible = todoAddState.todoFilterBottomSheetState, + selectedItem = todoAddState.selectedFilter, + onSelectedItemChanged = onFilterBottomSheetItemClicked, + onDismissRequest = onFilterBottomSheetDismissRequest + ) +} \ No newline at end of file diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingViewModel.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingViewModel.kt new file mode 100644 index 00000000..a9dd6cb8 --- /dev/null +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingViewModel.kt @@ -0,0 +1,111 @@ +package org.android.bbangzip.presentation.ui.todo.pendingtodoadd + +import android.os.Parcelable +import androidx.lifecycle.SavedStateHandle +import dagger.hilt.android.lifecycle.HiltViewModel +import org.android.bbangzip.presentation.component.card.BbangZipCardState +import org.android.bbangzip.presentation.util.base.BaseViewModel +import javax.inject.Inject + +@HiltViewModel +class TodoAddPendingViewModel +@Inject +constructor( + savedStateHandle: SavedStateHandle, +) : BaseViewModel( + savedStateHandle = savedStateHandle, +) { + override fun createInitialState(savedState: Parcelable?): TodoAddPendingContract.TodoAddPendingState { + return savedState as? TodoAddPendingContract.TodoAddPendingState ?: TodoAddPendingContract.TodoAddPendingState() + } + + override fun handleEvent(event: TodoAddPendingContract.TodoAddPendingEvent) { + when (event) { + TodoAddPendingContract.TodoAddPendingEvent.Initialize -> TODO() + + TodoAddPendingContract.TodoAddPendingEvent.OnBackIconClicked -> { + updateState(TodoAddPendingContract.TodoAddPendingReduce.ResetSelectedItemList) + setSideEffect(TodoAddPendingContract.TodoAddPendingSideEffect.NavigateToBack) + } + + TodoAddPendingContract.TodoAddPendingEvent.OnFilterBottomSheetDismissRequest -> updateState( + TodoAddPendingContract.TodoAddPendingReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = false + ) + ) + + TodoAddPendingContract.TodoAddPendingEvent.OnFilterIconClicked -> updateState( + TodoAddPendingContract.TodoAddPendingReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = true + ) + ) + + is TodoAddPendingContract.TodoAddPendingEvent.OnFilterBottomSheetItemClicked -> { + updateState(TodoAddPendingContract.TodoAddPendingReduce.UpdateFilterType(selectedFilter = event.selectedFilterItem)) + updateState( + TodoAddPendingContract.TodoAddPendingReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = false + ) + ) + setSideEffect(TodoAddPendingContract.TodoAddPendingSideEffect.ShowTodoAddSnackBar("${event.selectedFilterItem.filter}으로 정렬했어요")) + //TODO 받아오고 다시 정렬해야됨 ㅋㅋ + } + + TodoAddPendingContract.TodoAddPendingEvent.OnItemPlusButtonClicked -> { + // TODO 서버로 보내기 + setSideEffect(TodoAddPendingContract.TodoAddPendingSideEffect.NavigateToToDo) + setSideEffect(TodoAddPendingContract.TodoAddPendingSideEffect.ShowSnackBar("오늘 할 공부를 추가했어요!")) + } + + is TodoAddPendingContract.TodoAddPendingEvent.OnToDoCardClicked -> { + if (event.cardState == BbangZipCardState.CHECKED) { + updateState(TodoAddPendingContract.TodoAddPendingReduce.UpdateSelectedItemList(pieceId = event.pieceId)) + updateState( + TodoAddPendingContract.TodoAddPendingReduce.UpdateCardState( + pieceId = event.pieceId, + cardState = event.cardState + ) + ) + } else { + updateState(TodoAddPendingContract.TodoAddPendingReduce.DeleteSelectedItemList(pieceId = event.pieceId)) + updateState( + TodoAddPendingContract.TodoAddPendingReduce.UpdateCardState( + pieceId = event.pieceId, + cardState = event.cardState + ) + ) + } + } + } + } + + override fun reduceState(state: TodoAddPendingContract.TodoAddPendingState, reduce: TodoAddPendingContract.TodoAddPendingReduce): TodoAddPendingContract.TodoAddPendingState { + return when (reduce) { + TodoAddPendingContract.TodoAddPendingReduce.ResetSelectedItemList -> state.copy( + selectedItemList = listOf() + ) + + is TodoAddPendingContract.TodoAddPendingReduce.UpdateCardState -> state.copy( + todoList = state.todoList.map { item -> + if (item.pieceId == reduce.pieceId) item.copy(cardState = reduce.cardState) else item + } + ) + + is TodoAddPendingContract.TodoAddPendingReduce.UpdateFilterType -> state.copy( + selectedFilter = reduce.selectedFilter + ) + + is TodoAddPendingContract.TodoAddPendingReduce.UpdateSelectedItemList -> state.copy( + selectedItemList = state.selectedItemList.plus(reduce.pieceId) + ) + + is TodoAddPendingContract.TodoAddPendingReduce.UpdateToDoFilterBottomSheetState -> state.copy( + todoFilterBottomSheetState = reduce.todoFilterBottomSheetState + ) + + is TodoAddPendingContract.TodoAddPendingReduce.DeleteSelectedItemList -> state.copy( + selectedItemList = state.selectedItemList.minus(reduce.pieceId) + ) + } + } +} \ No newline at end of file From 31ad277fd0238d551c00909883e0c6b416f45a17 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sun, 19 Jan 2025 17:20:04 +0900 Subject: [PATCH 31/40] =?UTF-8?q?[feat]=20#31=20ktlint=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bbangzip/domain/model/ToDoInfoEntity.kt | 6 +- .../presentation/component/card/ToDoCard.kt | 178 +++--- .../presentation/type/ToDoFilterType.kt | 3 - .../presentation/type/ToDoScreenType.kt | 4 +- .../presentation/ui/navigator/MainNavHost.kt | 16 +- .../ui/navigator/MainNavigator.kt | 1 - .../presentation/ui/todo/TodoContract.kt | 236 ++++---- .../presentation/ui/todo/TodoRoute.kt | 5 +- .../presentation/ui/todo/TodoScreen.kt | 527 +++++++++--------- .../presentation/ui/todo/TodoViewModel.kt | 498 +++++++++-------- .../ui/todo/navigation/TodoNavigation.kt | 4 +- .../pendingtodoadd/TodoAddPendingContract.kt | 235 ++++---- .../pendingtodoadd/TodoAddPendingRoute.kt | 4 +- .../pendingtodoadd/TodoAddPendingScreen.kt | 63 ++- .../pendingtodoadd/TodoAddPendingViewModel.kt | 170 +++--- .../navigation/TodoAddPendingNavigation.kt | 2 +- .../ui/todo/todoadd/TodoAddContract.kt | 235 ++++---- .../ui/todo/todoadd/TodoAddRoute.kt | 4 +- .../ui/todo/todoadd/TodoAddScreen.kt | 85 +-- .../ui/todo/todoadd/TodoAddViewModel.kt | 170 +++--- .../todoadd/navigation/TodoAddNavigation.kt | 2 +- .../presentation/util/base/BaseViewModel.kt | 1 - .../presentation/util/modifier/ModifierExt.kt | 3 +- 23 files changed, 1257 insertions(+), 1195 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/domain/model/ToDoInfoEntity.kt b/app/src/main/java/org/android/bbangzip/domain/model/ToDoInfoEntity.kt index c64aee05..edd5fb72 100644 --- a/app/src/main/java/org/android/bbangzip/domain/model/ToDoInfoEntity.kt +++ b/app/src/main/java/org/android/bbangzip/domain/model/ToDoInfoEntity.kt @@ -1,8 +1,8 @@ package org.android.bbangzip.domain.model data class ToDoInfoEntity( - val todoList : List, + val todoList: List, val pendingCount: Int, - val remainingStudyCount : Int, - val completeCount : Int, + val remainingStudyCount: Int, + val completeCount: Int, ) diff --git a/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt b/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt index db4d8968..9dd5c7cd 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/component/card/ToDoCard.kt @@ -42,32 +42,32 @@ fun ToDoCard( val infoOpacity = state.getInfoOpacity() Box( modifier = - modifier - .applyShadows( - shadowType = state.getShadowOptions(), - shape = RoundedCornerShape(size = radius), - ) - .fillMaxWidth() - .border( - width = state.getBorderWidth(), - color = state.getBorderColor(), - shape = RoundedCornerShape(size = radius), - ) - .background( - color = state.getBackgroundColor(), - shape = RoundedCornerShape(size = radius), - ) - .applyFilterOnClick( - baseColor = state.getBackgroundColor(), - isDisabled = false, - radius = radius, - ) { onClick() } - .padding(horizontal = 16.dp, vertical = 10.dp), + modifier + .applyShadows( + shadowType = state.getShadowOptions(), + shape = RoundedCornerShape(size = radius), + ) + .fillMaxWidth() + .border( + width = state.getBorderWidth(), + color = state.getBorderColor(), + shape = RoundedCornerShape(size = radius), + ) + .background( + color = state.getBackgroundColor(), + shape = RoundedCornerShape(size = radius), + ) + .applyFilterOnClick( + baseColor = state.getBackgroundColor(), + isDisabled = false, + radius = radius, + ) { onClick() } + .padding(horizontal = 16.dp, vertical = 10.dp), ) { Row( modifier = - Modifier - .fillMaxWidth(), + Modifier + .fillMaxWidth(), horizontalArrangement = Arrangement.SpaceBetween, ) { ToDoInfo( @@ -114,11 +114,11 @@ fun ToDoInfo( if (data.subjectName.isNotBlank() && data.examName.isNotBlank()) { Text( text = - stringResource( - R.string.card_subject_exam_name_text, - data.subjectName, - data.examName, - ), + stringResource( + R.string.card_subject_exam_name_text, + data.subjectName, + data.examName, + ), style = BbangZipTheme.typography.caption2Medium, color = getColor(BbangZipTheme.colors.labelAssistive_282119_28), ) @@ -136,11 +136,11 @@ fun ToDoInfo( Text( text = - stringResource( - R.string.card_start_end_day_text, - data.startPage, - data.finishPage, - ), + stringResource( + R.string.card_start_end_day_text, + data.startPage, + data.finishPage, + ), style = BbangZipTheme.typography.label1Bold, color = getColor(BbangZipTheme.colors.labelNormal_282119), ) @@ -174,10 +174,10 @@ fun CheckSpace( Box( contentAlignment = Alignment.Center, modifier = - modifier - .background(color = backgroundColor, shape = RoundedCornerShape(12.dp)) - .height(32.dp) - .width(32.dp), + modifier + .background(color = backgroundColor, shape = RoundedCornerShape(12.dp)) + .height(32.dp) + .width(32.dp), ) { if (isCompleted) { Icon( @@ -196,71 +196,71 @@ fun ToDoCardPreview() { Column { ToDoCard( data = - ToDoCardModel( - subjectName = "경제통계학개론", - examName = "중간고사", - studyContents = "경제통계학", - startPage = 36, - finishPage = 60, - deadline = "2025년 4월 25일", - pieceId = 1, - remainingDays = 1, - cardState = BbangZipCardState.DEFAULT, - ), + ToDoCardModel( + subjectName = "경제통계학개론", + examName = "중간고사", + studyContents = "경제통계학", + startPage = 36, + finishPage = 60, + deadline = "2025년 4월 25일", + pieceId = 1, + remainingDays = 1, + cardState = BbangZipCardState.DEFAULT, + ), modifier = - Modifier - .padding(16.dp), + Modifier + .padding(16.dp), ) ToDoCard( data = - ToDoCardModel( - subjectName = "경제통계학개론", - examName = "중간고사", - studyContents = "경제통계학", - startPage = 36, - finishPage = 60, - deadline = "2025년 4월 25일", - pieceId = 1, - remainingDays = 1, - cardState = BbangZipCardState.CHECKED, - ), + ToDoCardModel( + subjectName = "경제통계학개론", + examName = "중간고사", + studyContents = "경제통계학", + startPage = 36, + finishPage = 60, + deadline = "2025년 4월 25일", + pieceId = 1, + remainingDays = 1, + cardState = BbangZipCardState.CHECKED, + ), modifier = - Modifier - .padding(16.dp), + Modifier + .padding(16.dp), ) ToDoCard( data = - ToDoCardModel( - subjectName = "", - examName = "", - studyContents = "경제통계학", - startPage = 36, - finishPage = 60, - deadline = "2025년 4월 25일", - pieceId = 1, - remainingDays = 1, - cardState = BbangZipCardState.CHECKABLE, - ), + ToDoCardModel( + subjectName = "", + examName = "", + studyContents = "경제통계학", + startPage = 36, + finishPage = 60, + deadline = "2025년 4월 25일", + pieceId = 1, + remainingDays = 1, + cardState = BbangZipCardState.CHECKABLE, + ), modifier = - Modifier - .padding(16.dp), + Modifier + .padding(16.dp), ) ToDoCard( data = - ToDoCardModel( - subjectName = "경제통계학개론", - examName = "중간고사", - studyContents = "경제통계학", - startPage = 36, - finishPage = 60, - deadline = "2025년 4월 25일", - pieceId = 1, - remainingDays = 1, - cardState = BbangZipCardState.COMPLETE, - ), + ToDoCardModel( + subjectName = "경제통계학개론", + examName = "중간고사", + studyContents = "경제통계학", + startPage = 36, + finishPage = 60, + deadline = "2025년 4월 25일", + pieceId = 1, + remainingDays = 1, + cardState = BbangZipCardState.COMPLETE, + ), modifier = - Modifier - .padding(16.dp), + Modifier + .padding(16.dp), ) } } diff --git a/app/src/main/java/org/android/bbangzip/presentation/type/ToDoFilterType.kt b/app/src/main/java/org/android/bbangzip/presentation/type/ToDoFilterType.kt index 72901b60..33ebd416 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/type/ToDoFilterType.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/type/ToDoFilterType.kt @@ -1,8 +1,5 @@ package org.android.bbangzip.presentation.type -import androidx.annotation.StringRes -import org.android.bbangzip.R - enum class ToDoFilterType( val filter: String, val id: String, diff --git a/app/src/main/java/org/android/bbangzip/presentation/type/ToDoScreenType.kt b/app/src/main/java/org/android/bbangzip/presentation/type/ToDoScreenType.kt index 4c36f293..40dfa6bb 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/type/ToDoScreenType.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/type/ToDoScreenType.kt @@ -3,5 +3,5 @@ package org.android.bbangzip.presentation.type enum class ToDoScreenType { EMPTY, DEFAULT, - DELETE -} \ No newline at end of file + DELETE, +} diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt index a87de4cb..d1153fa5 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt @@ -15,8 +15,8 @@ import org.android.bbangzip.presentation.ui.my.myNavGraph import org.android.bbangzip.presentation.ui.subject.navigateSubject import org.android.bbangzip.presentation.ui.subject.subjectNavGraph import org.android.bbangzip.presentation.ui.todo.navigation.todoNavGraph -import org.android.bbangzip.presentation.ui.todo.todoadd.navigation.todoAddNavGraph import org.android.bbangzip.presentation.ui.todo.pendingtodoadd.navigation.todoAddPendingNavGraph +import org.android.bbangzip.presentation.ui.todo.todoadd.navigation.todoAddNavGraph import org.android.bbangzip.ui.theme.BbangZipTheme @Composable @@ -28,10 +28,10 @@ fun MainNavHost( ) { Box( modifier = - modifier - .padding(top = padding.calculateTopPadding()) - .fillMaxSize() - .background(BbangZipTheme.colors.backgroundNormal_FFFFFF), + modifier + .padding(top = padding.calculateTopPadding()) + .fillMaxSize() + .background(BbangZipTheme.colors.backgroundNormal_FFFFFF), ) { NavHost( navController = navigator.navHostController, @@ -48,13 +48,13 @@ fun MainNavHost( todoAddNavGraph( snackBarHostState = snackBarHostState, navigateToBack = { navigator.popBackStackIfNotSubject() }, - navigateToToDo = { navigator.popBackStackIfNotSubject() } + navigateToToDo = { navigator.popBackStackIfNotSubject() }, ) todoAddPendingNavGraph( snackBarHostState = snackBarHostState, navigateToBack = { navigator.popBackStackIfNotSubject() }, - navigateToToDo = { navigator.popBackStackIfNotSubject() } + navigateToToDo = { navigator.popBackStackIfNotSubject() }, ) friendNavGraph() @@ -66,7 +66,7 @@ fun MainNavHost( todoNavGraph( snackBarHostState = snackBarHostState, navigateToAddToDo = { navigator.navigateToToDoAdd() }, - navigateToAddPendingToDo = {navigator.navigateToToDoAddPending()}, + navigateToAddPendingToDo = { navigator.navigateToToDoAddPending() }, ) } } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt index e482d319..a275d581 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavigator.kt @@ -76,7 +76,6 @@ class MainNavigator( navHostController.popBackStack() } - fun popBackStackIfNotSubject() { if (!isSameCurrentDestination()) { popBackStack() diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt index de87cdd8..7d03204a 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt @@ -11,117 +11,119 @@ import org.android.bbangzip.presentation.util.base.BaseContract class TodoContract { @Parcelize data class TodoState( - val todoList: List = listOf( - ToDoCardModel( - pieceId = 1, - subjectName = "Math", - examName = "Algebra Exam", - studyContents = "Review Chapters 1-3", - startPage = 1, - finishPage = 50, - deadline = "2025-01-20", - remainingDays = 2, - cardState = BbangZipCardState.DEFAULT + val todoList: List = + listOf( + ToDoCardModel( + pieceId = 1, + subjectName = "Math", + examName = "Algebra Exam", + studyContents = "Review Chapters 1-3", + startPage = 1, + finishPage = 50, + deadline = "2025-01-20", + remainingDays = 2, + cardState = BbangZipCardState.DEFAULT, + ), + ToDoCardModel( + pieceId = 2, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = -3, + cardState = BbangZipCardState.COMPLETE, + ), + ToDoCardModel( + pieceId = 3, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 7, + cardState = BbangZipCardState.DEFAULT, + ), + ToDoCardModel( + pieceId = 4, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Complete abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = -2, + cardState = BbangZipCardState.COMPLETE, + ), + ToDoCardModel( + pieceId = 5, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = 4, + cardState = BbangZipCardState.DEFAULT, + ), + ToDoCardModel( + pieceId = 6, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = -1, + cardState = BbangZipCardState.COMPLETE, + ), + ToDoCardModel( + pieceId = 7, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Complete abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = 5, + cardState = BbangZipCardState.DEFAULT, + ), + ToDoCardModel( + pieceId = 8, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = -4, + cardState = BbangZipCardState.COMPLETE, + ), + ToDoCardModel( + pieceId = 9, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 3, + cardState = BbangZipCardState.DEFAULT, + ), + ToDoCardModel( + pieceId = 10, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Complete abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = -5, + cardState = BbangZipCardState.COMPLETE, + ), ), - ToDoCardModel( - pieceId = 2, - subjectName = "History", - examName = "World War II Quiz", - studyContents = "Notes on WWII", - startPage = 5, - finishPage = 30, - deadline = "2025-01-22", - remainingDays = -3, - cardState = BbangZipCardState.COMPLETE - ), - ToDoCardModel( - pieceId = 3, - subjectName = "Science", - examName = "Physics Midterm", - studyContents = "Kinematics and Dynamics", - startPage = 20, - finishPage = 80, - deadline = "2025-01-25", - remainingDays = 7, - cardState = BbangZipCardState.DEFAULT - ), - ToDoCardModel( - pieceId = 4, - subjectName = "Art", - examName = "Painting Project", - studyContents = "Complete abstract art piece", - startPage = 0, - finishPage = 0, - deadline = "2025-01-28", - remainingDays = -2, - cardState = BbangZipCardState.COMPLETE - ), - ToDoCardModel( - pieceId = 5, - subjectName = "History", - examName = "World War II Quiz", - studyContents = "Notes on WWII", - startPage = 5, - finishPage = 30, - deadline = "2025-01-22", - remainingDays = 4, - cardState = BbangZipCardState.DEFAULT - ), - ToDoCardModel( - pieceId = 6, - subjectName = "Science", - examName = "Physics Midterm", - studyContents = "Kinematics and Dynamics", - startPage = 20, - finishPage = 80, - deadline = "2025-01-25", - remainingDays = -1, - cardState = BbangZipCardState.COMPLETE - ), - ToDoCardModel( - pieceId = 7, - subjectName = "Art", - examName = "Painting Project", - studyContents = "Complete abstract art piece", - startPage = 0, - finishPage = 0, - deadline = "2025-01-28", - remainingDays = 5, - cardState = BbangZipCardState.DEFAULT - ), - ToDoCardModel( - pieceId = 8, - subjectName = "History", - examName = "World War II Quiz", - studyContents = "Notes on WWII", - startPage = 5, - finishPage = 30, - deadline = "2025-01-22", - remainingDays = -4, - cardState = BbangZipCardState.COMPLETE - ), - ToDoCardModel( - pieceId = 9, - subjectName = "Science", - examName = "Physics Midterm", - studyContents = "Kinematics and Dynamics", - startPage = 20, - finishPage = 80, - deadline = "2025-01-25", - remainingDays = 3, - cardState = BbangZipCardState.DEFAULT - ), - ToDoCardModel( - pieceId = 10, - subjectName = "Art", - examName = "Painting Project", - studyContents = "Complete abstract art piece", - startPage = 0, - finishPage = 0, - deadline = "2025-01-28", - remainingDays = -5, - cardState = BbangZipCardState.COMPLETE - )), val pendingCount: Int = 10, val remainingStudyCount: Int = 5, val completeCount: Int = 5, @@ -129,7 +131,7 @@ class TodoContract { val selectedFilterItem: ToDoFilterType = ToDoFilterType.RECENT, val selectedItemList: List = listOf(), val revertCompleteBottomSheetState: Boolean = false, - val screenType: ToDoScreenType = ToDoScreenType.EMPTY + val screenType: ToDoScreenType = ToDoScreenType.EMPTY, ) : BaseContract.State, Parcelable { override fun toParcelable(): Parcelable = this } @@ -163,16 +165,16 @@ class TodoContract { val todoList: List, val pendingCount: Int, val remainingStudyCount: Int, - val completeCount: Int + val completeCount: Int, ) : TodoEvent data class OnFilterBottomSheetItemClicked( - val selectedFilterItem: ToDoFilterType + val selectedFilterItem: ToDoFilterType, ) : TodoEvent data class OnDeleteScreenCardClicked( val pieceId: Int, - val cardState: BbangZipCardState + val cardState: BbangZipCardState, ) : TodoEvent @@ -203,16 +205,16 @@ class TodoContract { data class UpdateCardState( val pieceId: Int, - val cardState: BbangZipCardState + val cardState: BbangZipCardState, ) : TodoReduce data class UpdateToDoListCardState( val previousCardState: BbangZipCardState, - val nextCardState: BbangZipCardState + val nextCardState: BbangZipCardState, ) : TodoReduce data class UpdateFilterType( - val selectedFilter: ToDoFilterType + val selectedFilter: ToDoFilterType, ) : TodoReduce data class UpdatePendingToDoCount(val pendingCount: Int) : TodoReduce diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt index 1fade72d..9e1cec44 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt @@ -19,7 +19,7 @@ fun TodoRoute( snackBarHostState: SnackbarHostState, navigateToAddToDo: () -> Unit = {}, navigateToAddPendingToDo: () -> Unit = {}, - viewModel: TodoViewModel = hiltViewModel() + viewModel: TodoViewModel = hiltViewModel(), ) { val todoState by viewModel.uiState.collectAsStateWithLifecycle() val success by viewModel.success.collectAsStateWithLifecycle(initialValue = true) @@ -63,7 +63,7 @@ fun TodoRoute( }, onRevertCompleteBottomSheetApproveButtonClicked = { pieceId -> viewModel.setEvent( - TodoContract.TodoEvent.OnRevertCompleteBottomSheetApproveButtonClicked(pieceId = pieceId) + TodoContract.TodoEvent.OnRevertCompleteBottomSheetApproveButtonClicked(pieceId = pieceId), ) }, onRevertCompleteBottomSheetDismissRequest = { @@ -96,6 +96,5 @@ fun TodoRoute( ) false -> Text("땡!") - } } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt index e34a0284..c8391426 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt @@ -66,17 +66,18 @@ fun TodoScreen( onDefaultScreenCardClicked: (Int, BbangZipCardState) -> Unit = { _, _ -> }, ) { Box( - modifier = modifier - .fillMaxSize() - .padding(bottom = 74.dp) - .background(color = BbangZipTheme.colors.staticWhite_FFFFFF) + modifier = + modifier + .fillMaxSize() + .padding(bottom = 74.dp) + .background(color = BbangZipTheme.colors.staticWhite_FFFFFF), ) { LazyColumn { item { DateMessageCard( todayDate = todayDate, pendingCount = todoState.pendingCount, - onAddPendingStudyButtonClicked = onAddPendingStudyButtonClicked + onAddPendingStudyButtonClicked = onAddPendingStudyButtonClicked, ) Spacer(Modifier.height(48.dp)) @@ -112,29 +113,32 @@ fun TodoScreen( text = stringResource(R.string.todo_delete_screen_text), style = BbangZipTheme.typography.heading2Bold, color = BbangZipTheme.colors.labelNormal_282119, - modifier = Modifier.padding(start = 24.dp) + modifier = Modifier.padding(start = 24.dp), ) Spacer(Modifier.height(4.dp)) Row( - modifier = Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically + modifier = + Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, ) { Spacer(modifier = Modifier.weight(1f)) Box( - modifier = Modifier - .clip(CircleShape) - .clickable { onCloseIconClicked() }, contentAlignment = Alignment.Center + modifier = + Modifier + .clip(CircleShape) + .clickable { onCloseIconClicked() }, + contentAlignment = Alignment.Center, ) { Icon( imageVector = ImageVector.vectorResource(R.drawable.ic_x_small_24), contentDescription = null, modifier = Modifier.padding(8.dp), - tint = BbangZipTheme.colors.labelAlternative_282119_61 + tint = BbangZipTheme.colors.labelAlternative_282119_61, ) } } @@ -147,7 +151,8 @@ fun TodoScreen( count = todoState.todoList.size, key = { index -> todoState.todoList[index].pieceId - }) { index -> + }, + ) { index -> ToDoCard( data = todoState.todoList[index], modifier = Modifier.padding(horizontal = 16.dp, vertical = 6.dp), @@ -156,34 +161,34 @@ fun TodoScreen( (todoState.screenType == ToDoScreenType.DEFAULT) && (todoState.todoList[index].cardState == BbangZipCardState.DEFAULT) -> onDefaultScreenCardClicked( todoState.todoList[index].pieceId, - BbangZipCardState.COMPLETE + BbangZipCardState.COMPLETE, ) (todoState.screenType == ToDoScreenType.DEFAULT) && (todoState.todoList[index].cardState == BbangZipCardState.COMPLETE) -> onDefaultScreenCardClicked( todoState.todoList[index].pieceId, - BbangZipCardState.DEFAULT + BbangZipCardState.DEFAULT, ) (todoState.screenType == ToDoScreenType.DELETE) && (todoState.todoList[index].cardState == BbangZipCardState.CHECKED) -> onDeleteScreenCardClicked( todoState.todoList[index].pieceId, - BbangZipCardState.CHECKABLE + BbangZipCardState.CHECKABLE, ) (todoState.screenType == ToDoScreenType.DELETE) && (todoState.todoList[index].cardState == BbangZipCardState.CHECKABLE) -> onDeleteScreenCardClicked( todoState.todoList[index].pieceId, - BbangZipCardState.CHECKED + BbangZipCardState.CHECKED, ) else -> onDeleteScreenCardClicked( todoState.todoList[index].pieceId, - BbangZipCardState.COMPLETE + BbangZipCardState.COMPLETE, ) } - } + }, ) } } @@ -194,11 +199,12 @@ fun TodoScreen( bbangZipButtonSize = BbangZipButtonSize.Large, onClick = { onItemDeleteButtonClicked() }, label = stringResource(R.string.todo_delete_screen_delete_button_text, todoState.selectedItemList.size), - modifier = Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth() - .align(Alignment.BottomCenter) - .padding(bottom = 6.dp), + modifier = + Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth() + .align(Alignment.BottomCenter) + .padding(bottom = 6.dp), isEnable = todoState.selectedItemList.isNotEmpty(), trailingIcon = R.drawable.ic_plus_thick_24, ) @@ -210,29 +216,29 @@ fun TodoScreen( bottomSheetTitle = "미완료 상태로 되돌릴까요?", onDismissRequest = onRevertCompleteBottomSheetDismissRequest, onClickInteractButton = onRevertCompleteBottomSheetApproveButtonClicked, - onClickCancelButton = onRevertCompleteBottomSheetDismissButtonClicked + onClickCancelButton = onRevertCompleteBottomSheetDismissButtonClicked, ) BbangZipToDoFilterPickerBottomSheet( isBottomSheetVisible = todoState.todoFilterBottomSheetState, selectedItem = todoState.selectedFilterItem, onSelectedItemChanged = onFilterBottomSheetItemClicked, - onDismissRequest = onFilterBottomSheetDismissRequest + onDismissRequest = onFilterBottomSheetDismissRequest, ) } } - @Composable fun DateMessageCard( todayDate: List, pendingCount: Int, onAddPendingStudyButtonClicked: () -> Unit, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { Box( - modifier = modifier - .fillMaxWidth() + modifier = + modifier + .fillMaxWidth(), ) { Column(modifier = Modifier.fillMaxWidth()) { Column( @@ -240,24 +246,24 @@ fun DateMessageCard( .background(color = BbangZipTheme.colors.backgroundAccent_FFDAA0, shape = RoundedCornerShape(bottomEnd = 32.dp, bottomStart = 32.dp)) .fillMaxWidth() .height(LocalConfiguration.current.screenHeightDp.dp * (172f / 764f)) - .padding(start = 24.dp) + .padding(start = 24.dp), ) { Spacer(modifier = Modifier.height(44.dp)) Row( verticalAlignment = Alignment.CenterVertically, - modifier = Modifier.padding(start = 8.dp) + modifier = Modifier.padding(start = 8.dp), ) { Text( text = todayDate[0].toInt().toString(), style = BbangZipTheme.typography.title3Bold, - color = BbangZipTheme.colors.labelNormal_282119 + color = BbangZipTheme.colors.labelNormal_282119, ) Text( text = stringResource(R.string.todo_month_text), style = BbangZipTheme.typography.headline1Bold, - color = BbangZipTheme.colors.labelAlternative_282119_61 + color = BbangZipTheme.colors.labelAlternative_282119_61, ) Spacer(modifier = Modifier.width(8.dp)) @@ -265,13 +271,13 @@ fun DateMessageCard( Text( text = todayDate[1].toInt().toString(), style = BbangZipTheme.typography.title3Bold, - color = BbangZipTheme.colors.labelNormal_282119 + color = BbangZipTheme.colors.labelNormal_282119, ) Text( text = stringResource(R.string.todo_day_text), style = BbangZipTheme.typography.headline1Bold, - color = BbangZipTheme.colors.labelAlternative_282119_61 + color = BbangZipTheme.colors.labelAlternative_282119_61, ) Spacer(modifier = Modifier.width(8.dp)) @@ -279,7 +285,7 @@ fun DateMessageCard( Text( text = todayDate[2], style = BbangZipTheme.typography.body1Bold, - color = BbangZipTheme.colors.labelNormal_282119 + color = BbangZipTheme.colors.labelNormal_282119, ) } @@ -289,7 +295,7 @@ fun DateMessageCard( Text( text = stringResource(R.string.todo_pending_count_text), style = BbangZipTheme.typography.headline1Bold, - color = BbangZipTheme.colors.labelAlternative_282119_61 + color = BbangZipTheme.colors.labelAlternative_282119_61, ) Spacer(modifier = Modifier.height(62.dp)) @@ -316,13 +322,13 @@ fun DateMessageCard( Icon( imageVector = ImageVector.vectorResource(id = R.drawable.ic_announcement_default_24), contentDescription = null, - tint = BbangZipTheme.colors.labelNormal_282119 + tint = BbangZipTheme.colors.labelNormal_282119, ) Spacer(modifier = Modifier.width(6.dp)) }, horizontalPadding = 16.dp, - modifier = Modifier.align(Alignment.BottomCenter) + modifier = Modifier.align(Alignment.BottomCenter), ) } } @@ -331,29 +337,35 @@ fun DateMessageCard( fun StudyCountText( remainingCount: Int, completeCount: Int, - modifier: Modifier = Modifier + modifier: Modifier = Modifier, ) { Column( - modifier = modifier - .padding(horizontal = 16.dp) - .fillMaxWidth() - .padding(start = 8.dp) + modifier = + modifier + .padding(horizontal = 16.dp) + .fillMaxWidth() + .padding(start = 8.dp), ) { Text( - text = when { - completeCount > 0 && remainingCount != 0 -> stringResource(R.string.todo_complete_count_text, completeCount) - remainingCount == 0 -> stringResource(R.string.todo_complete_remaining_nothing_text) - else -> stringResource(R.string.todo_complete_nothing_text) - }, + text = + when { + completeCount > 0 && remainingCount != 0 -> stringResource(R.string.todo_complete_count_text, completeCount) + remainingCount == 0 -> stringResource(R.string.todo_complete_remaining_nothing_text) + else -> stringResource(R.string.todo_complete_nothing_text) + }, style = BbangZipTheme.typography.label1Bold, - color = BbangZipTheme.colors.labelAlternative_282119_61 + color = BbangZipTheme.colors.labelAlternative_282119_61, ) Text( - text = if (remainingCount != 0) stringResource(R.string.todo_remaing_count_text, remainingCount) - else stringResource(R.string.todo_remaining_nothing_text), + text = + if (remainingCount != 0) { + stringResource(R.string.todo_remaing_count_text, remainingCount) + } else { + stringResource(R.string.todo_remaining_nothing_text) + }, style = BbangZipTheme.typography.title3Bold, - color = BbangZipTheme.colors.labelNormal_282119 + color = BbangZipTheme.colors.labelNormal_282119, ) } } @@ -365,37 +377,41 @@ fun DeleteAndFilterIcons( onFilterIconClicked: () -> Unit = {}, ) { Row( - modifier = modifier - .padding(horizontal = 16.dp) - .fillMaxWidth(), - verticalAlignment = Alignment.CenterVertically + modifier = + modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), + verticalAlignment = Alignment.CenterVertically, ) { Spacer(modifier = Modifier.weight(1f)) Box( - modifier = Modifier - .clip(CircleShape) - .clickable { onDeleteIconClicked() }, contentAlignment = Alignment.Center + modifier = + Modifier + .clip(CircleShape) + .clickable { onDeleteIconClicked() }, + contentAlignment = Alignment.Center, ) { Icon( imageVector = ImageVector.vectorResource(R.drawable.ic_trash_default_24), contentDescription = null, modifier = Modifier.padding(8.dp), - tint = BbangZipTheme.colors.labelAlternative_282119_61 + tint = BbangZipTheme.colors.labelAlternative_282119_61, ) } Box( - modifier = Modifier - .clip(CircleShape) - .clickable { onFilterIconClicked() }, contentAlignment = Alignment.Center + modifier = + Modifier + .clip(CircleShape) + .clickable { onFilterIconClicked() }, + contentAlignment = Alignment.Center, ) { Icon( imageVector = ImageVector.vectorResource(R.drawable.ic_filter_default_24), contentDescription = null, modifier = Modifier.padding(8.dp), - tint = BbangZipTheme.colors.labelAlternative_282119_61 - + tint = BbangZipTheme.colors.labelAlternative_282119_61, ) } } @@ -404,14 +420,16 @@ fun DeleteAndFilterIcons( @Composable fun EmptyView( modifier: Modifier = Modifier, - onAddStudyButtonClicked: () -> Unit = {} + onAddStudyButtonClicked: () -> Unit = {}, ) { Column(modifier = modifier.padding(horizontal = 16.dp)) { Box( - modifier = Modifier - .fillMaxWidth() - .height(328.dp) - .background(color = BbangZipTheme.colors.backgroundAlternative_F5F5F5, shape = RoundedCornerShape(size = 32.dp)), contentAlignment = Alignment.Center + modifier = + Modifier + .fillMaxWidth() + .height(328.dp) + .background(color = BbangZipTheme.colors.backgroundAlternative_F5F5F5, shape = RoundedCornerShape(size = 32.dp)), + contentAlignment = Alignment.Center, ) { Text(text = "Empty View") } @@ -457,14 +475,14 @@ fun BbangZipToDoFilterPickerBottomSheet( Text( text = item.filter, modifier = - Modifier - .fillMaxWidth() - .applyFilterOnClick { onSelectedItemChanged(item) } - .background( - color = if (item != selectedItem) BbangZipTheme.colors.staticWhite_FFFFFF else BbangZipTheme.colors.fillStrong_68645E_16, - shape = RoundedCornerShape(16.dp), - ) - .padding(vertical = 8.dp), + Modifier + .fillMaxWidth() + .applyFilterOnClick { onSelectedItemChanged(item) } + .background( + color = if (item != selectedItem) BbangZipTheme.colors.staticWhite_FFFFFF else BbangZipTheme.colors.fillStrong_68645E_16, + shape = RoundedCornerShape(16.dp), + ) + .padding(vertical = 8.dp), textAlign = TextAlign.Center, style = BbangZipTheme.typography.body1Bold, color = BbangZipTheme.colors.labelNormal_282119, @@ -494,9 +512,9 @@ fun RevertCompleteBottomSheet( Text( text = bottomSheetTitle, modifier = - Modifier - .align(Alignment.CenterHorizontally) - .padding(vertical = 15.dp), + Modifier + .align(Alignment.CenterHorizontally) + .padding(vertical = 15.dp), style = BbangZipTheme.typography.headline1Bold, color = BbangZipTheme.colors.labelNeutral_282119_88, ) @@ -518,7 +536,7 @@ fun RevertCompleteBottomSheet( BbangZipButton( bbangZipButtonType = BbangZipButtonType.Outlined, bbangZipButtonSize = BbangZipButtonSize.Large, - onClick = onClickCancelButton, + onClick = onClickCancelButton, label = stringResource(R.string.btn_cancle_label), modifier = Modifier.fillMaxWidth(), ) @@ -526,182 +544,183 @@ fun RevertCompleteBottomSheet( ) } - @Preview(showBackground = true) @Composable fun TodoScreenMockPreview() { - val mockToDoList = listOf( - ToDoCardModel( - pieceId = 1, - subjectName = "Math", - examName = "Algebra Exam", - studyContents = "Review Chapters 1-3", - startPage = 1, - finishPage = 50, - deadline = "2025-01-20", - remainingDays = 2, - cardState = BbangZipCardState.DEFAULT - ), - ToDoCardModel( - pieceId = 2, - subjectName = "History", - examName = "World War II Quiz", - studyContents = "Notes on WWII", - startPage = 5, - finishPage = 30, - deadline = "2025-01-22", - remainingDays = 4, - cardState = BbangZipCardState.COMPLETE - ), - ToDoCardModel( - pieceId = 3, - subjectName = "Science", - examName = "Physics Midterm", - studyContents = "Kinematics and Dynamics", - startPage = 20, - finishPage = 80, - deadline = "2025-01-25", - remainingDays = 7, - cardState = BbangZipCardState.CHECKED - ), - ToDoCardModel( - pieceId = 4, - subjectName = "Art", - examName = "Painting Project", - studyContents = "Complete abstract art piece", - startPage = 0, - finishPage = 0, - deadline = "2025-01-28", - remainingDays = 10, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 2, - subjectName = "History", - examName = "World War II Quiz", - studyContents = "Notes on WWII", - startPage = 5, - finishPage = 30, - deadline = "2025-01-22", - remainingDays = 4, - cardState = BbangZipCardState.COMPLETE - ), - ToDoCardModel( - pieceId = 3, - subjectName = "Science", - examName = "Physics Midterm", - studyContents = "Kinematics and Dynamics", - startPage = 20, - finishPage = 80, - deadline = "2025-01-25", - remainingDays = 7, - cardState = BbangZipCardState.CHECKED - ), - ToDoCardModel( - pieceId = 4, - subjectName = "Art", - examName = "Painting Project", - studyContents = "Complete abstract art piece", - startPage = 0, - finishPage = 0, - deadline = "2025-01-28", - remainingDays = 10, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 2, - subjectName = "History", - examName = "World War II Quiz", - studyContents = "Notes on WWII", - startPage = 5, - finishPage = 30, - deadline = "2025-01-22", - remainingDays = 4, - cardState = BbangZipCardState.COMPLETE - ), - ToDoCardModel( - pieceId = 3, - subjectName = "Science", - examName = "Physics Midterm", - studyContents = "Kinematics and Dynamics", - startPage = 20, - finishPage = 80, - deadline = "2025-01-25", - remainingDays = 7, - cardState = BbangZipCardState.CHECKED - ), - ToDoCardModel( - pieceId = 4, - subjectName = "Art", - examName = "Painting Project", - studyContents = "Complete abstract art piece", - startPage = 0, - finishPage = 0, - deadline = "2025-01-28", - remainingDays = 10, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 2, - subjectName = "History", - examName = "World War II Quiz", - studyContents = "Notes on WWII", - startPage = 5, - finishPage = 30, - deadline = "2025-01-22", - remainingDays = 4, - cardState = BbangZipCardState.COMPLETE - ), - ToDoCardModel( - pieceId = 3, - subjectName = "Science", - examName = "Physics Midterm", - studyContents = "Kinematics and Dynamics", - startPage = 20, - finishPage = 80, - deadline = "2025-01-25", - remainingDays = 7, - cardState = BbangZipCardState.CHECKED - ), - ToDoCardModel( - pieceId = 4, - subjectName = "Art", - examName = "Painting Project", - studyContents = "Complete abstract art piece", - startPage = 0, - finishPage = 0, - deadline = "2025-01-28", - remainingDays = 10, - cardState = BbangZipCardState.CHECKABLE + val mockToDoList = + listOf( + ToDoCardModel( + pieceId = 1, + subjectName = "Math", + examName = "Algebra Exam", + studyContents = "Review Chapters 1-3", + startPage = 1, + finishPage = 50, + deadline = "2025-01-20", + remainingDays = 2, + cardState = BbangZipCardState.DEFAULT, + ), + ToDoCardModel( + pieceId = 2, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = 4, + cardState = BbangZipCardState.COMPLETE, + ), + ToDoCardModel( + pieceId = 3, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 7, + cardState = BbangZipCardState.CHECKED, + ), + ToDoCardModel( + pieceId = 4, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Complete abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = 10, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 2, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = 4, + cardState = BbangZipCardState.COMPLETE, + ), + ToDoCardModel( + pieceId = 3, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 7, + cardState = BbangZipCardState.CHECKED, + ), + ToDoCardModel( + pieceId = 4, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Complete abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = 10, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 2, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = 4, + cardState = BbangZipCardState.COMPLETE, + ), + ToDoCardModel( + pieceId = 3, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 7, + cardState = BbangZipCardState.CHECKED, + ), + ToDoCardModel( + pieceId = 4, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Complete abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = 10, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 2, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = 4, + cardState = BbangZipCardState.COMPLETE, + ), + ToDoCardModel( + pieceId = 3, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 7, + cardState = BbangZipCardState.CHECKED, + ), + ToDoCardModel( + pieceId = 4, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Complete abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = 10, + cardState = BbangZipCardState.CHECKABLE, + ), ) - ) - val mockTodoStates = listOf( - TodoContract.TodoState( - todoList = mockToDoList, - pendingCount = 2, - remainingStudyCount = 1, - completeCount = 1, - screenType = ToDoScreenType.DEFAULT - ), - TodoContract.TodoState( - todoList = mockToDoList, - pendingCount = 1, - remainingStudyCount = 0, - completeCount = 3, - screenType = ToDoScreenType.DELETE - ), - TodoContract.TodoState( - todoList = mockToDoList, - pendingCount = 0, - remainingStudyCount = 2, - completeCount = 2, - screenType = ToDoScreenType.EMPTY + val mockTodoStates = + listOf( + TodoContract.TodoState( + todoList = mockToDoList, + pendingCount = 2, + remainingStudyCount = 1, + completeCount = 1, + screenType = ToDoScreenType.DEFAULT, + ), + TodoContract.TodoState( + todoList = mockToDoList, + pendingCount = 1, + remainingStudyCount = 0, + completeCount = 3, + screenType = ToDoScreenType.DELETE, + ), + TodoContract.TodoState( + todoList = mockToDoList, + pendingCount = 0, + remainingStudyCount = 2, + completeCount = 2, + screenType = ToDoScreenType.EMPTY, + ), ) - ) TodoScreen( todoState = mockTodoStates[0], todayDate = listOf("2025", "01", "18"), ) -} \ No newline at end of file +} diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt index a3efd089..76852b20 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoViewModel.kt @@ -10,302 +10,314 @@ import javax.inject.Inject @HiltViewModel class TodoViewModel -@Inject -constructor( - savedStateHandle: SavedStateHandle, -) : BaseViewModel( - savedStateHandle = savedStateHandle, -) { - override fun createInitialState(savedState: Parcelable?): TodoContract.TodoState { - return savedState as? TodoContract.TodoState ?: TodoContract.TodoState() - } + @Inject + constructor( + savedStateHandle: SavedStateHandle, + ) : BaseViewModel( + savedStateHandle = savedStateHandle, + ) { + override fun createInitialState(savedState: Parcelable?): TodoContract.TodoState { + return savedState as? TodoContract.TodoState ?: TodoContract.TodoState() + } - init { - setEvent(TodoContract.TodoEvent.Initialize) - } + init { + setEvent(TodoContract.TodoEvent.Initialize) + } - override fun handleEvent(event: TodoContract.TodoEvent) { - when (event) { - //ToDoInfo Fetch - is TodoContract.TodoEvent.FetchToDoInfo -> updateState( - TodoContract.TodoReduce.UpdateToDoInfo( - pendingCount = event.pendingCount, - remainingStudyCount = event.remainingStudyCount, - completeCount = event.completeCount, - todoList = event.todoList - ) - ) + override fun handleEvent(event: TodoContract.TodoEvent) { + when (event) { + // ToDoInfo Fetch + is TodoContract.TodoEvent.FetchToDoInfo -> + updateState( + TodoContract.TodoReduce.UpdateToDoInfo( + pendingCount = event.pendingCount, + remainingStudyCount = event.remainingStudyCount, + completeCount = event.completeCount, + todoList = event.todoList, + ), + ) - TodoContract.TodoEvent.Initialize -> launch { initDataLoad() } + TodoContract.TodoEvent.Initialize -> launch { initDataLoad() } - //Filter BottomSheet - is TodoContract.TodoEvent.OnFilterBottomSheetItemClicked -> { - updateState(TodoContract.TodoReduce.UpdateFilterType(selectedFilter = event.selectedFilterItem)) - updateState( - TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState( - todoFilterBottomSheetState = false + // Filter BottomSheet + is TodoContract.TodoEvent.OnFilterBottomSheetItemClicked -> { + updateState(TodoContract.TodoReduce.UpdateFilterType(selectedFilter = event.selectedFilterItem)) + updateState( + TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = false, + ), ) - ) - setSideEffect(TodoContract.TodoSideEffect.ShowSnackBar("${event.selectedFilterItem.filter}으로 정렬했어요")) - //TODO index를 이용해 서버로 FetchInfo 보내주기 다시 정렬하기 ㅋㅋ - } - - TodoContract.TodoEvent.OnFilterBottomSheetDismissRequest -> updateState( - TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState( - todoFilterBottomSheetState = false - ) - ) + setSideEffect(TodoContract.TodoSideEffect.ShowSnackBar("${event.selectedFilterItem.filter}으로 정렬했어요")) + // TODO index를 이용해 서버로 FetchInfo 보내주기 다시 정렬하기 ㅋㅋ + } - TodoContract.TodoEvent.OnFilterIconClicked -> { - updateState( - TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState( - todoFilterBottomSheetState = true + TodoContract.TodoEvent.OnFilterBottomSheetDismissRequest -> + updateState( + TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = false, + ), ) - ) - } + TodoContract.TodoEvent.OnFilterIconClicked -> { + updateState( + TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = true, + ), + ) + } - //revertComplete BottomSheet - is TodoContract.TodoEvent.OnRevertCompleteBottomSheetApproveButtonClicked -> { - updateState( - TodoContract.TodoReduce.UpdateCardState( - pieceId = event.pieceId, - cardState = BbangZipCardState.DEFAULT + // revertComplete BottomSheet + is TodoContract.TodoEvent.OnRevertCompleteBottomSheetApproveButtonClicked -> { + updateState( + TodoContract.TodoReduce.UpdateCardState( + pieceId = event.pieceId, + cardState = BbangZipCardState.DEFAULT, + ), ) - ) - updateState( - TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState( - revertCompleteBottomSheetState = false + updateState( + TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState( + revertCompleteBottomSheetState = false, + ), ) - ) - updateState( - TodoContract.TodoReduce.UpdateToDoCount( - completeCount = currentUiState.completeCount - 1, - remainingStudyCount = currentUiState.remainingStudyCount + 1 + updateState( + TodoContract.TodoReduce.UpdateToDoCount( + completeCount = currentUiState.completeCount - 1, + remainingStudyCount = currentUiState.remainingStudyCount + 1, + ), ) - ) - updateState(TodoContract.TodoReduce.ResetSelectedItemList) - setSideEffect(TodoContract.TodoSideEffect.ShowSnackBar("미완료 상태로 되돌려졌어요!")) - //TODO pieceId 사영헤사 서버로 쏘기 미완료 APT - } + updateState(TodoContract.TodoReduce.ResetSelectedItemList) + setSideEffect(TodoContract.TodoSideEffect.ShowSnackBar("미완료 상태로 되돌려졌어요!")) + // TODO pieceId 사영헤사 서버로 쏘기 미완료 APT + } - TodoContract.TodoEvent.OnRevertCompleteBottomSheetDismissButtonClicked -> { - updateState( - TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState( - revertCompleteBottomSheetState = false + TodoContract.TodoEvent.OnRevertCompleteBottomSheetDismissButtonClicked -> { + updateState( + TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState( + revertCompleteBottomSheetState = false, + ), ) - ) - updateState(TodoContract.TodoReduce.ResetSelectedItemList) - } + updateState(TodoContract.TodoReduce.ResetSelectedItemList) + } - TodoContract.TodoEvent.OnRevertCompleteBottomSheetDismissRequest -> { - updateState( - TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState( - revertCompleteBottomSheetState = false + TodoContract.TodoEvent.OnRevertCompleteBottomSheetDismissRequest -> { + updateState( + TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState( + revertCompleteBottomSheetState = false, + ), ) - ) - updateState(TodoContract.TodoReduce.ResetSelectedItemList) - } + updateState(TodoContract.TodoReduce.ResetSelectedItemList) + } - //Delete - is TodoContract.TodoEvent.OnDeleteScreenCardClicked -> { - when (event.cardState) { - BbangZipCardState.CHECKED -> { - updateState(TodoContract.TodoReduce.UpdateSelectedItemList(pieceId = event.pieceId)) - updateState( - TodoContract.TodoReduce.UpdateCardState( - pieceId = event.pieceId, - cardState = event.cardState + // Delete + is TodoContract.TodoEvent.OnDeleteScreenCardClicked -> { + when (event.cardState) { + BbangZipCardState.CHECKED -> { + updateState(TodoContract.TodoReduce.UpdateSelectedItemList(pieceId = event.pieceId)) + updateState( + TodoContract.TodoReduce.UpdateCardState( + pieceId = event.pieceId, + cardState = event.cardState, + ), ) - ) - } + } + + BbangZipCardState.CHECKABLE -> { + updateState(TodoContract.TodoReduce.DeleteSelectedItemList(pieceId = event.pieceId)) + updateState( + TodoContract.TodoReduce.UpdateCardState( + pieceId = event.pieceId, + cardState = event.cardState, + ), + ) + } - BbangZipCardState.CHECKABLE -> { - updateState(TodoContract.TodoReduce.DeleteSelectedItemList(pieceId = event.pieceId)) + else -> { + setSideEffect(TodoContract.TodoSideEffect.ShowSnackBar("이미 완료한 일은 삭제할 수 없어요!")) + } + } + } + // Default + is TodoContract.TodoEvent.OnDefaultScreenCardClicked -> { + if (event.cardState == BbangZipCardState.COMPLETE) { updateState( TodoContract.TodoReduce.UpdateCardState( pieceId = event.pieceId, - cardState = event.cardState - ) + cardState = event.cardState, + ), ) + updateState( + TodoContract.TodoReduce.UpdateToDoCount( + completeCount = currentUiState.completeCount + 1, + remainingStudyCount = currentUiState.remainingStudyCount - 1, + ), + ) + TodoContract.TodoSideEffect.ShowSnackBar("공부완료 ! 오늘의 빵굽기 성공!") + } else { + updateState( + TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState( + revertCompleteBottomSheetState = true, + ), + ) + updateState(TodoContract.TodoReduce.UpdateSelectedItemList(pieceId = event.pieceId)) } - - else -> { - setSideEffect(TodoContract.TodoSideEffect.ShowSnackBar("이미 완료한 일은 삭제할 수 없어요!")) - } + // TODO 서버로 pieceId 이용해서 완료 API 쏘기 } - } - //Default - is TodoContract.TodoEvent.OnDefaultScreenCardClicked -> { - if (event.cardState == BbangZipCardState.COMPLETE) { + + TodoContract.TodoEvent.OnDeleteIconClicked -> { + updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.DELETE)) updateState( - TodoContract.TodoReduce.UpdateCardState( - pieceId = event.pieceId, - cardState = event.cardState - ) + TodoContract.TodoReduce.UpdateToDoListCardState( + previousCardState = BbangZipCardState.DEFAULT, + nextCardState = BbangZipCardState.CHECKABLE, + ), ) + } + + TodoContract.TodoEvent.OnItemDeleteButtonClicked -> { + // TODO setlectedItemlist 사용해서 서버로 삭제한 card API 전송 updateState( TodoContract.TodoReduce.UpdateToDoCount( - completeCount = currentUiState.completeCount + 1, - remainingStudyCount = currentUiState.remainingStudyCount - 1 - ) + completeCount = currentUiState.completeCount, + remainingStudyCount = currentUiState.remainingStudyCount - currentUiState.selectedItemList.size, + ), ) - TodoContract.TodoSideEffect.ShowSnackBar("공부완료 ! 오늘의 빵굽기 성공!") - } else { - updateState( - TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState( - revertCompleteBottomSheetState = true + if (currentUiState.remainingStudyCount != 0) { + updateState(TodoContract.TodoReduce.DeleteToDoListItems) + updateState( + TodoContract.TodoReduce.UpdateToDoListCardState( + previousCardState = BbangZipCardState.CHECKABLE, + nextCardState = BbangZipCardState.DEFAULT, + ), ) - ) - updateState(TodoContract.TodoReduce.UpdateSelectedItemList(pieceId = event.pieceId)) - + updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.DEFAULT)) + } else { + updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.EMPTY)) + } + updateState(TodoContract.TodoReduce.ResetSelectedItemList) + setSideEffect(TodoContract.TodoSideEffect.ShowSnackBar("오늘 할 공부를 삭제했어요")) } - // TODO 서버로 pieceId 이용해서 완료 API 쏘기 - } -//통과!! - TodoContract.TodoEvent.OnDeleteIconClicked -> { - updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.DELETE)) - updateState( - TodoContract.TodoReduce.UpdateToDoListCardState( - previousCardState = BbangZipCardState.DEFAULT, - nextCardState = BbangZipCardState.CHECKABLE - ) - ) - } - - TodoContract.TodoEvent.OnItemDeleteButtonClicked -> { - //TODO setlectedItemlist 사용해서 서버로 삭제한 card API 전송 - updateState( - TodoContract.TodoReduce.UpdateToDoCount( - completeCount = currentUiState.completeCount, - remainingStudyCount = currentUiState.remainingStudyCount - currentUiState.selectedItemList.size - ) - ) - if (currentUiState.remainingStudyCount != 0) { - updateState(TodoContract.TodoReduce.DeleteToDoListItems) +// 통과 + TodoContract.TodoEvent.OnCloseIconClicked -> { updateState( TodoContract.TodoReduce.UpdateToDoListCardState( previousCardState = BbangZipCardState.CHECKABLE, - nextCardState = BbangZipCardState.DEFAULT - ) + nextCardState = BbangZipCardState.DEFAULT, + ), ) + updateState( + TodoContract.TodoReduce.UpdateToDoListCardState( + previousCardState = BbangZipCardState.CHECKED, + nextCardState = BbangZipCardState.DEFAULT, + ), + ) + updateState(TodoContract.TodoReduce.ResetSelectedItemList) updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.DEFAULT)) - - } else { - updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.EMPTY)) } - updateState(TodoContract.TodoReduce.ResetSelectedItemList) - setSideEffect(TodoContract.TodoSideEffect.ShowSnackBar("오늘 할 공부를 삭제했어요")) - } -// 통과 - TodoContract.TodoEvent.OnCloseIconClicked -> { - updateState( - TodoContract.TodoReduce.UpdateToDoListCardState( - previousCardState = BbangZipCardState.CHECKABLE, - nextCardState = BbangZipCardState.DEFAULT - ) - ) - updateState( - TodoContract.TodoReduce.UpdateToDoListCardState( - previousCardState = BbangZipCardState.CHECKED, - nextCardState = BbangZipCardState.DEFAULT - ) - ) - updateState(TodoContract.TodoReduce.ResetSelectedItemList) - updateState(TodoContract.TodoReduce.UpdateScreenType(screenType = ToDoScreenType.DEFAULT)) - } - //화면 이동 - TodoContract.TodoEvent.OnAddStudyButtonClicked -> setSideEffect(TodoContract.TodoSideEffect.NavigateToAddToDo) - TodoContract.TodoEvent.OnAddPendingStudyButtonClicked -> setSideEffect(TodoContract.TodoSideEffect.NavigateToAddPendingToDo) + // 화면 이동 + TodoContract.TodoEvent.OnAddStudyButtonClicked -> setSideEffect(TodoContract.TodoSideEffect.NavigateToAddToDo) + TodoContract.TodoEvent.OnAddPendingStudyButtonClicked -> setSideEffect(TodoContract.TodoSideEffect.NavigateToAddPendingToDo) + } } - } - override fun reduceState( - state: TodoContract.TodoState, - reduce: TodoContract.TodoReduce - ): TodoContract.TodoState { - return when (reduce) { - //ToDoInfo Fetch - is TodoContract.TodoReduce.UpdateToDoInfo -> state.copy( - pendingCount = reduce.pendingCount, - completeCount = reduce.completeCount, - remainingStudyCount = reduce.remainingStudyCount, - todoList = reduce.todoList - ) + override fun reduceState( + state: TodoContract.TodoState, + reduce: TodoContract.TodoReduce, + ): TodoContract.TodoState { + return when (reduce) { + // ToDoInfo Fetch + is TodoContract.TodoReduce.UpdateToDoInfo -> + state.copy( + pendingCount = reduce.pendingCount, + completeCount = reduce.completeCount, + remainingStudyCount = reduce.remainingStudyCount, + todoList = reduce.todoList, + ) - //List - is TodoContract.TodoReduce.UpdateCardState -> state.copy( - todoList = state.todoList.map { item -> - if (item.pieceId == reduce.pieceId) item.copy(cardState = reduce.cardState) else item - } - ) + // List + is TodoContract.TodoReduce.UpdateCardState -> + state.copy( + todoList = + state.todoList.map { item -> + if (item.pieceId == reduce.pieceId) item.copy(cardState = reduce.cardState) else item + }, + ) - is TodoContract.TodoReduce.UpdateToDoListCardState -> state.copy( // 해당 카드스태이트를 찾아서 바꿔줌 - todoList = state.todoList.map { item -> - if (item.cardState == reduce.previousCardState) { - item.copy(cardState = reduce.nextCardState) - } else item - } - ) + is TodoContract.TodoReduce.UpdateToDoListCardState -> + state.copy( + todoList = + state.todoList.map { item -> + if (item.cardState == reduce.previousCardState) { + item.copy(cardState = reduce.nextCardState) + } else { + item + } + }, + ) - is TodoContract.TodoReduce.DeleteToDoListItems -> { - val pieceIdSet = currentUiState.selectedItemList.toSet() - state.copy( - todoList = state.todoList.filter { item -> - item.pieceId !in pieceIdSet - } - ) - } + is TodoContract.TodoReduce.DeleteToDoListItems -> { + val pieceIdSet = currentUiState.selectedItemList.toSet() + state.copy( + todoList = + state.todoList.filter { item -> + item.pieceId !in pieceIdSet + }, + ) + } - //Revert BottomSheet - is TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState -> state.copy( - revertCompleteBottomSheetState = reduce.revertCompleteBottomSheetState - ) + // Revert BottomSheet + is TodoContract.TodoReduce.UpdateRevertCompleteBottomSheetState -> + state.copy( + revertCompleteBottomSheetState = reduce.revertCompleteBottomSheetState, + ) - is TodoContract.TodoReduce.UpdateSelectedItemList -> state.copy( - selectedItemList = state.selectedItemList.plus(reduce.pieceId) - ) + is TodoContract.TodoReduce.UpdateSelectedItemList -> + state.copy( + selectedItemList = state.selectedItemList.plus(reduce.pieceId), + ) - is TodoContract.TodoReduce.DeleteSelectedItemList -> state.copy( - selectedItemList = state.selectedItemList.minus(reduce.pieceId) - ) + is TodoContract.TodoReduce.DeleteSelectedItemList -> + state.copy( + selectedItemList = state.selectedItemList.minus(reduce.pieceId), + ) - //Filter BottomSheet - is TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState -> state.copy( - todoFilterBottomSheetState = reduce.todoFilterBottomSheetState - ) + // Filter BottomSheet + is TodoContract.TodoReduce.UpdateToDoFilterBottomSheetState -> + state.copy( + todoFilterBottomSheetState = reduce.todoFilterBottomSheetState, + ) - is TodoContract.TodoReduce.UpdateFilterType -> state.copy( - selectedFilterItem = reduce.selectedFilter - ) + is TodoContract.TodoReduce.UpdateFilterType -> + state.copy( + selectedFilterItem = reduce.selectedFilter, + ) - //ToDoCount - is TodoContract.TodoReduce.UpdateToDoCount -> { - state.copy( - completeCount = reduce.completeCount, - remainingStudyCount = reduce.remainingStudyCount - ) - } + // ToDoCount + is TodoContract.TodoReduce.UpdateToDoCount -> { + state.copy( + completeCount = reduce.completeCount, + remainingStudyCount = reduce.remainingStudyCount, + ) + } - is TodoContract.TodoReduce.UpdatePendingToDoCount -> state.copy( - pendingCount = reduce.pendingCount - ) + is TodoContract.TodoReduce.UpdatePendingToDoCount -> + state.copy( + pendingCount = reduce.pendingCount, + ) - //ScreenType - is TodoContract.TodoReduce.UpdateScreenType -> state.copy( - screenType = reduce.screenType - ) + // ScreenType + is TodoContract.TodoReduce.UpdateScreenType -> + state.copy( + screenType = reduce.screenType, + ) - TodoContract.TodoReduce.ResetSelectedItemList -> state.copy( - selectedItemList = listOf() - ) + TodoContract.TodoReduce.ResetSelectedItemList -> + state.copy( + selectedItemList = listOf(), + ) + } } - } - - private fun initDataLoad() { + private fun initDataLoad() { + } } - - -} \ No newline at end of file diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt index c96f215d..2f1944b6 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt @@ -18,13 +18,13 @@ fun NavController.navigateTodo(navOptions: NavOptions) { fun NavGraphBuilder.todoNavGraph( snackBarHostState: SnackbarHostState, navigateToAddToDo: () -> Unit, - navigateToAddPendingToDo: () -> Unit = {} + navigateToAddPendingToDo: () -> Unit = {}, ) { composable { TodoRoute( snackBarHostState = snackBarHostState, navigateToAddToDo = navigateToAddToDo, - navigateToAddPendingToDo = navigateToAddPendingToDo + navigateToAddPendingToDo = navigateToAddPendingToDo, ) } } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingContract.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingContract.kt index 30e1a539..7d96f5e1 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingContract.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingContract.kt @@ -10,118 +10,119 @@ import org.android.bbangzip.presentation.util.base.BaseContract class TodoAddPendingContract { @Parcelize data class TodoAddPendingState( - val todoList: List = listOf( - ToDoCardModel( - pieceId = 1, - subjectName = "Math", - examName = "Algebra Exam", - studyContents = "Review Chapters 1-3", - startPage = 1, - finishPage = 50, - deadline = "2025-01-20", - remainingDays = 2, - cardState = BbangZipCardState.CHECKABLE + val todoList: List = + listOf( + ToDoCardModel( + pieceId = 1, + subjectName = "Math", + examName = "Algebra Exam", + studyContents = "Review Chapters 1-3", + startPage = 1, + finishPage = 50, + deadline = "2025-01-20", + remainingDays = 2, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 2, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = -3, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 3, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 7, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 4, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Checkable abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = -2, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 5, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = 4, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 6, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = -1, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 7, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Checkable abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = 5, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 8, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = -4, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 9, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 3, + cardState = BbangZipCardState.DEFAULT, + ), + ToDoCardModel( + pieceId = 10, + subjectName = "Art", + examName = "Painting Project", + studyContents = "CHECKABLE abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = -5, + cardState = BbangZipCardState.CHECKABLE, + ), ), - ToDoCardModel( - pieceId = 2, - subjectName = "History", - examName = "World War II Quiz", - studyContents = "Notes on WWII", - startPage = 5, - finishPage = 30, - deadline = "2025-01-22", - remainingDays = -3, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 3, - subjectName = "Science", - examName = "Physics Midterm", - studyContents = "Kinematics and Dynamics", - startPage = 20, - finishPage = 80, - deadline = "2025-01-25", - remainingDays = 7, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 4, - subjectName = "Art", - examName = "Painting Project", - studyContents = "Checkable abstract art piece", - startPage = 0, - finishPage = 0, - deadline = "2025-01-28", - remainingDays = -2, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 5, - subjectName = "History", - examName = "World War II Quiz", - studyContents = "Notes on WWII", - startPage = 5, - finishPage = 30, - deadline = "2025-01-22", - remainingDays = 4, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 6, - subjectName = "Science", - examName = "Physics Midterm", - studyContents = "Kinematics and Dynamics", - startPage = 20, - finishPage = 80, - deadline = "2025-01-25", - remainingDays = -1, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 7, - subjectName = "Art", - examName = "Painting Project", - studyContents = "Checkable abstract art piece", - startPage = 0, - finishPage = 0, - deadline = "2025-01-28", - remainingDays = 5, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 8, - subjectName = "History", - examName = "World War II Quiz", - studyContents = "Notes on WWII", - startPage = 5, - finishPage = 30, - deadline = "2025-01-22", - remainingDays = -4, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 9, - subjectName = "Science", - examName = "Physics Midterm", - studyContents = "Kinematics and Dynamics", - startPage = 20, - finishPage = 80, - deadline = "2025-01-25", - remainingDays = 3, - cardState = BbangZipCardState.DEFAULT - ), - ToDoCardModel( - pieceId = 10, - subjectName = "Art", - examName = "Painting Project", - studyContents = "CHECKABLE abstract art piece", - startPage = 0, - finishPage = 0, - deadline = "2025-01-28", - remainingDays = -5, - cardState = BbangZipCardState.CHECKABLE - ) - ), val todoFilterBottomSheetState: Boolean = false, val selectedFilter: ToDoFilterType = ToDoFilterType.RECENT, val selectedItemList: List = listOf(), @@ -149,24 +150,24 @@ class TodoAddPendingContract { data object ResetSelectedItemList : TodoAddPendingReduce data class UpdateSelectedItemList( - val pieceId: Int + val pieceId: Int, ) : TodoAddPendingReduce data class UpdateToDoFilterBottomSheetState( - val todoFilterBottomSheetState: Boolean + val todoFilterBottomSheetState: Boolean, ) : TodoAddPendingReduce data class UpdateFilterType( - val selectedFilter: ToDoFilterType + val selectedFilter: ToDoFilterType, ) : TodoAddPendingReduce data class DeleteSelectedItemList( - val pieceId: Int + val pieceId: Int, ) : TodoAddPendingReduce data class UpdateCardState( val pieceId: Int, - val cardState: BbangZipCardState + val cardState: BbangZipCardState, ) : TodoAddPendingReduce } @@ -179,4 +180,4 @@ class TodoAddPendingContract { data class ShowTodoAddSnackBar(val message: String) : TodoAddPendingSideEffect } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingRoute.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingRoute.kt index 059e57c5..525e47fa 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingRoute.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingRoute.kt @@ -17,7 +17,7 @@ fun TodoAddPendingRoute( snackBarHostState: SnackbarHostState, navigateToToDo: () -> Unit = {}, navigateToBack: () -> Unit = {}, - viewModel: TodoAddPendingViewModel = hiltViewModel() + viewModel: TodoAddPendingViewModel = hiltViewModel(), ) { val todoAddPendingState by viewModel.uiState.collectAsStateWithLifecycle() val success by viewModel.success.collectAsStateWithLifecycle(initialValue = true) @@ -77,7 +77,7 @@ fun TodoAddPendingRoute( }, onToDoCardClicked = { pieceId, cardState -> viewModel.setEvent(TodoAddPendingContract.TodoAddPendingEvent.OnToDoCardClicked(pieceId = pieceId, cardState = cardState)) - } + }, ) false -> diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt index 6eff35c9..2695631a 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt @@ -53,9 +53,10 @@ fun TodoAddPendingScreen( onToDoCardClicked: (Int, BbangZipCardState) -> Unit = { _, _ -> }, ) { Box( - modifier = modifier - .fillMaxSize() - .background(color = BbangZipTheme.colors.staticWhite_FFFFFF) + modifier = + modifier + .fillMaxSize() + .background(color = BbangZipTheme.colors.staticWhite_FFFFFF), ) { Column { val scrollState = rememberLazyListState() @@ -68,16 +69,17 @@ fun TodoAddPendingScreen( isShadowed = isShadowed, title = "", leadingIcon = R.drawable.ic_chevronleft_thick_small_24, - onLeadingIconClick = onBackIconClicked + onLeadingIconClick = onBackIconClicked, ) Spacer(modifier = Modifier.height(32.dp)) LazyColumn( - modifier = Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth(), - state = scrollState + modifier = + Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), + state = scrollState, ) { item { Text(text = stringResource(R.string.todo_pending_add_title1), style = BbangZipTheme.typography.body1Bold, color = BbangZipTheme.colors.labelAlternative_282119_61) @@ -91,27 +93,27 @@ fun TodoAddPendingScreen( item { Row( - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { Spacer(modifier = Modifier.width(8.dp)) - Text(text = "${todoAddState.selectedItemList.size} ", style = BbangZipTheme.typography.body2Bold, color = BbangZipTheme.colors.labelNormal_282119) Text(text = stringResource(R.string.todo_add_count, todoAddState.todoList.size), style = BbangZipTheme.typography.body2Bold, color = BbangZipTheme.colors.labelAlternative_282119_61) Spacer(modifier = Modifier.weight(1f)) Box( - modifier = Modifier - .clip(CircleShape) - .clickable { onFilterIconClicked() }, contentAlignment = Alignment.Center + modifier = + Modifier + .clip(CircleShape) + .clickable { onFilterIconClicked() }, + contentAlignment = Alignment.Center, ) { Icon( imageVector = ImageVector.vectorResource(R.drawable.ic_filter_default_24), contentDescription = null, modifier = Modifier.padding(8.dp), - tint = BbangZipTheme.colors.labelAlternative_282119_61 - + tint = BbangZipTheme.colors.labelAlternative_282119_61, ) } } @@ -123,30 +125,32 @@ fun TodoAddPendingScreen( count = todoAddState.todoList.size, key = { index -> todoAddState.todoList[index].pieceId - }) { index -> + }, + ) { index -> ToDoCard( data = todoAddState.todoList[index], modifier = Modifier.padding(vertical = 6.dp), onClick = { - if (todoAddState.todoList[index].cardState == BbangZipCardState.CHECKED) + if (todoAddState.todoList[index].cardState == BbangZipCardState.CHECKED) { onToDoCardClicked( todoAddState.todoList[index].pieceId, - BbangZipCardState.CHECKABLE + BbangZipCardState.CHECKABLE, ) - else (todoAddState.todoList[index].cardState == BbangZipCardState.CHECKABLE) + } else { + (todoAddState.todoList[index].cardState == BbangZipCardState.CHECKABLE) + } onToDoCardClicked( todoAddState.todoList[index].pieceId, - BbangZipCardState.CHECKED + BbangZipCardState.CHECKED, ) - - } + }, ) } } } Column( modifier = Modifier.align(Alignment.BottomCenter), - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { BbangZipSnackBarHost(snackBarHostState = todoAddSnackBarHostState) @@ -155,10 +159,11 @@ fun TodoAddPendingScreen( bbangZipButtonSize = BbangZipButtonSize.Large, onClick = { onItemPlusButtonClicked() }, label = stringResource(R.string.todo_add_plus_button_label), - modifier = Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth() - .padding(bottom = 16.dp), + modifier = + Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth() + .padding(bottom = 16.dp), isEnable = todoAddState.selectedItemList.isNotEmpty(), trailingIcon = R.drawable.ic_plus_thick_24, ) @@ -168,6 +173,6 @@ fun TodoAddPendingScreen( isBottomSheetVisible = todoAddState.todoFilterBottomSheetState, selectedItem = todoAddState.selectedFilter, onSelectedItemChanged = onFilterBottomSheetItemClicked, - onDismissRequest = onFilterBottomSheetDismissRequest + onDismissRequest = onFilterBottomSheetDismissRequest, ) -} \ No newline at end of file +} diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingViewModel.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingViewModel.kt index a9dd6cb8..ec6c525f 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingViewModel.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingViewModel.kt @@ -9,103 +9,115 @@ import javax.inject.Inject @HiltViewModel class TodoAddPendingViewModel -@Inject -constructor( - savedStateHandle: SavedStateHandle, -) : BaseViewModel( - savedStateHandle = savedStateHandle, -) { - override fun createInitialState(savedState: Parcelable?): TodoAddPendingContract.TodoAddPendingState { - return savedState as? TodoAddPendingContract.TodoAddPendingState ?: TodoAddPendingContract.TodoAddPendingState() - } + @Inject + constructor( + savedStateHandle: SavedStateHandle, + ) : BaseViewModel( + savedStateHandle = savedStateHandle, + ) { + override fun createInitialState(savedState: Parcelable?): TodoAddPendingContract.TodoAddPendingState { + return savedState as? TodoAddPendingContract.TodoAddPendingState ?: TodoAddPendingContract.TodoAddPendingState() + } - override fun handleEvent(event: TodoAddPendingContract.TodoAddPendingEvent) { - when (event) { - TodoAddPendingContract.TodoAddPendingEvent.Initialize -> TODO() + override fun handleEvent(event: TodoAddPendingContract.TodoAddPendingEvent) { + when (event) { + TodoAddPendingContract.TodoAddPendingEvent.Initialize -> TODO() - TodoAddPendingContract.TodoAddPendingEvent.OnBackIconClicked -> { - updateState(TodoAddPendingContract.TodoAddPendingReduce.ResetSelectedItemList) - setSideEffect(TodoAddPendingContract.TodoAddPendingSideEffect.NavigateToBack) - } + TodoAddPendingContract.TodoAddPendingEvent.OnBackIconClicked -> { + updateState(TodoAddPendingContract.TodoAddPendingReduce.ResetSelectedItemList) + setSideEffect(TodoAddPendingContract.TodoAddPendingSideEffect.NavigateToBack) + } - TodoAddPendingContract.TodoAddPendingEvent.OnFilterBottomSheetDismissRequest -> updateState( - TodoAddPendingContract.TodoAddPendingReduce.UpdateToDoFilterBottomSheetState( - todoFilterBottomSheetState = false - ) - ) + TodoAddPendingContract.TodoAddPendingEvent.OnFilterBottomSheetDismissRequest -> + updateState( + TodoAddPendingContract.TodoAddPendingReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = false, + ), + ) - TodoAddPendingContract.TodoAddPendingEvent.OnFilterIconClicked -> updateState( - TodoAddPendingContract.TodoAddPendingReduce.UpdateToDoFilterBottomSheetState( - todoFilterBottomSheetState = true - ) - ) + TodoAddPendingContract.TodoAddPendingEvent.OnFilterIconClicked -> + updateState( + TodoAddPendingContract.TodoAddPendingReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = true, + ), + ) - is TodoAddPendingContract.TodoAddPendingEvent.OnFilterBottomSheetItemClicked -> { - updateState(TodoAddPendingContract.TodoAddPendingReduce.UpdateFilterType(selectedFilter = event.selectedFilterItem)) - updateState( - TodoAddPendingContract.TodoAddPendingReduce.UpdateToDoFilterBottomSheetState( - todoFilterBottomSheetState = false + is TodoAddPendingContract.TodoAddPendingEvent.OnFilterBottomSheetItemClicked -> { + updateState(TodoAddPendingContract.TodoAddPendingReduce.UpdateFilterType(selectedFilter = event.selectedFilterItem)) + updateState( + TodoAddPendingContract.TodoAddPendingReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = false, + ), ) - ) - setSideEffect(TodoAddPendingContract.TodoAddPendingSideEffect.ShowTodoAddSnackBar("${event.selectedFilterItem.filter}으로 정렬했어요")) - //TODO 받아오고 다시 정렬해야됨 ㅋㅋ - } + setSideEffect(TodoAddPendingContract.TodoAddPendingSideEffect.ShowTodoAddSnackBar("${event.selectedFilterItem.filter}으로 정렬했어요")) + // TODO 받아오고 다시 정렬해야됨 ㅋㅋ + } - TodoAddPendingContract.TodoAddPendingEvent.OnItemPlusButtonClicked -> { - // TODO 서버로 보내기 - setSideEffect(TodoAddPendingContract.TodoAddPendingSideEffect.NavigateToToDo) - setSideEffect(TodoAddPendingContract.TodoAddPendingSideEffect.ShowSnackBar("오늘 할 공부를 추가했어요!")) - } + TodoAddPendingContract.TodoAddPendingEvent.OnItemPlusButtonClicked -> { + // TODO 서버로 보내기 + setSideEffect(TodoAddPendingContract.TodoAddPendingSideEffect.NavigateToToDo) + setSideEffect(TodoAddPendingContract.TodoAddPendingSideEffect.ShowSnackBar("오늘 할 공부를 추가했어요!")) + } - is TodoAddPendingContract.TodoAddPendingEvent.OnToDoCardClicked -> { - if (event.cardState == BbangZipCardState.CHECKED) { - updateState(TodoAddPendingContract.TodoAddPendingReduce.UpdateSelectedItemList(pieceId = event.pieceId)) - updateState( - TodoAddPendingContract.TodoAddPendingReduce.UpdateCardState( - pieceId = event.pieceId, - cardState = event.cardState + is TodoAddPendingContract.TodoAddPendingEvent.OnToDoCardClicked -> { + if (event.cardState == BbangZipCardState.CHECKED) { + updateState(TodoAddPendingContract.TodoAddPendingReduce.UpdateSelectedItemList(pieceId = event.pieceId)) + updateState( + TodoAddPendingContract.TodoAddPendingReduce.UpdateCardState( + pieceId = event.pieceId, + cardState = event.cardState, + ), ) - ) - } else { - updateState(TodoAddPendingContract.TodoAddPendingReduce.DeleteSelectedItemList(pieceId = event.pieceId)) - updateState( - TodoAddPendingContract.TodoAddPendingReduce.UpdateCardState( - pieceId = event.pieceId, - cardState = event.cardState + } else { + updateState(TodoAddPendingContract.TodoAddPendingReduce.DeleteSelectedItemList(pieceId = event.pieceId)) + updateState( + TodoAddPendingContract.TodoAddPendingReduce.UpdateCardState( + pieceId = event.pieceId, + cardState = event.cardState, + ), ) - ) + } } } } - } - override fun reduceState(state: TodoAddPendingContract.TodoAddPendingState, reduce: TodoAddPendingContract.TodoAddPendingReduce): TodoAddPendingContract.TodoAddPendingState { - return when (reduce) { - TodoAddPendingContract.TodoAddPendingReduce.ResetSelectedItemList -> state.copy( - selectedItemList = listOf() - ) + override fun reduceState( + state: TodoAddPendingContract.TodoAddPendingState, + reduce: TodoAddPendingContract.TodoAddPendingReduce, + ): TodoAddPendingContract.TodoAddPendingState { + return when (reduce) { + TodoAddPendingContract.TodoAddPendingReduce.ResetSelectedItemList -> + state.copy( + selectedItemList = listOf(), + ) - is TodoAddPendingContract.TodoAddPendingReduce.UpdateCardState -> state.copy( - todoList = state.todoList.map { item -> - if (item.pieceId == reduce.pieceId) item.copy(cardState = reduce.cardState) else item - } - ) + is TodoAddPendingContract.TodoAddPendingReduce.UpdateCardState -> + state.copy( + todoList = + state.todoList.map { item -> + if (item.pieceId == reduce.pieceId) item.copy(cardState = reduce.cardState) else item + }, + ) - is TodoAddPendingContract.TodoAddPendingReduce.UpdateFilterType -> state.copy( - selectedFilter = reduce.selectedFilter - ) + is TodoAddPendingContract.TodoAddPendingReduce.UpdateFilterType -> + state.copy( + selectedFilter = reduce.selectedFilter, + ) - is TodoAddPendingContract.TodoAddPendingReduce.UpdateSelectedItemList -> state.copy( - selectedItemList = state.selectedItemList.plus(reduce.pieceId) - ) + is TodoAddPendingContract.TodoAddPendingReduce.UpdateSelectedItemList -> + state.copy( + selectedItemList = state.selectedItemList.plus(reduce.pieceId), + ) - is TodoAddPendingContract.TodoAddPendingReduce.UpdateToDoFilterBottomSheetState -> state.copy( - todoFilterBottomSheetState = reduce.todoFilterBottomSheetState - ) + is TodoAddPendingContract.TodoAddPendingReduce.UpdateToDoFilterBottomSheetState -> + state.copy( + todoFilterBottomSheetState = reduce.todoFilterBottomSheetState, + ) - is TodoAddPendingContract.TodoAddPendingReduce.DeleteSelectedItemList -> state.copy( - selectedItemList = state.selectedItemList.minus(reduce.pieceId) - ) + is TodoAddPendingContract.TodoAddPendingReduce.DeleteSelectedItemList -> + state.copy( + selectedItemList = state.selectedItemList.minus(reduce.pieceId), + ) + } } } -} \ No newline at end of file diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/navigation/TodoAddPendingNavigation.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/navigation/TodoAddPendingNavigation.kt index cdcb4aae..9a52fbbc 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/navigation/TodoAddPendingNavigation.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/navigation/TodoAddPendingNavigation.kt @@ -28,4 +28,4 @@ fun NavGraphBuilder.todoAddPendingNavGraph( navigateToBack = navigateToBack, ) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddContract.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddContract.kt index 23626783..da372a70 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddContract.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddContract.kt @@ -10,118 +10,119 @@ import org.android.bbangzip.presentation.util.base.BaseContract class TodoAddContract { @Parcelize data class TodoAddState( - val todoList: List = listOf( - ToDoCardModel( - pieceId = 1, - subjectName = "Math", - examName = "Algebra Exam", - studyContents = "Review Chapters 1-3", - startPage = 1, - finishPage = 50, - deadline = "2025-01-20", - remainingDays = 2, - cardState = BbangZipCardState.CHECKABLE + val todoList: List = + listOf( + ToDoCardModel( + pieceId = 1, + subjectName = "Math", + examName = "Algebra Exam", + studyContents = "Review Chapters 1-3", + startPage = 1, + finishPage = 50, + deadline = "2025-01-20", + remainingDays = 2, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 2, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = -3, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 3, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 7, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 4, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Checkable abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = -2, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 5, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = 4, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 6, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = -1, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 7, + subjectName = "Art", + examName = "Painting Project", + studyContents = "Checkable abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = 5, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 8, + subjectName = "History", + examName = "World War II Quiz", + studyContents = "Notes on WWII", + startPage = 5, + finishPage = 30, + deadline = "2025-01-22", + remainingDays = -4, + cardState = BbangZipCardState.CHECKABLE, + ), + ToDoCardModel( + pieceId = 9, + subjectName = "Science", + examName = "Physics Midterm", + studyContents = "Kinematics and Dynamics", + startPage = 20, + finishPage = 80, + deadline = "2025-01-25", + remainingDays = 3, + cardState = BbangZipCardState.DEFAULT, + ), + ToDoCardModel( + pieceId = 10, + subjectName = "Art", + examName = "Painting Project", + studyContents = "CHECKABLE abstract art piece", + startPage = 0, + finishPage = 0, + deadline = "2025-01-28", + remainingDays = -5, + cardState = BbangZipCardState.CHECKABLE, + ), ), - ToDoCardModel( - pieceId = 2, - subjectName = "History", - examName = "World War II Quiz", - studyContents = "Notes on WWII", - startPage = 5, - finishPage = 30, - deadline = "2025-01-22", - remainingDays = -3, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 3, - subjectName = "Science", - examName = "Physics Midterm", - studyContents = "Kinematics and Dynamics", - startPage = 20, - finishPage = 80, - deadline = "2025-01-25", - remainingDays = 7, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 4, - subjectName = "Art", - examName = "Painting Project", - studyContents = "Checkable abstract art piece", - startPage = 0, - finishPage = 0, - deadline = "2025-01-28", - remainingDays = -2, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 5, - subjectName = "History", - examName = "World War II Quiz", - studyContents = "Notes on WWII", - startPage = 5, - finishPage = 30, - deadline = "2025-01-22", - remainingDays = 4, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 6, - subjectName = "Science", - examName = "Physics Midterm", - studyContents = "Kinematics and Dynamics", - startPage = 20, - finishPage = 80, - deadline = "2025-01-25", - remainingDays = -1, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 7, - subjectName = "Art", - examName = "Painting Project", - studyContents = "Checkable abstract art piece", - startPage = 0, - finishPage = 0, - deadline = "2025-01-28", - remainingDays = 5, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 8, - subjectName = "History", - examName = "World War II Quiz", - studyContents = "Notes on WWII", - startPage = 5, - finishPage = 30, - deadline = "2025-01-22", - remainingDays = -4, - cardState = BbangZipCardState.CHECKABLE - ), - ToDoCardModel( - pieceId = 9, - subjectName = "Science", - examName = "Physics Midterm", - studyContents = "Kinematics and Dynamics", - startPage = 20, - finishPage = 80, - deadline = "2025-01-25", - remainingDays = 3, - cardState = BbangZipCardState.DEFAULT - ), - ToDoCardModel( - pieceId = 10, - subjectName = "Art", - examName = "Painting Project", - studyContents = "CHECKABLE abstract art piece", - startPage = 0, - finishPage = 0, - deadline = "2025-01-28", - remainingDays = -5, - cardState = BbangZipCardState.CHECKABLE - ) - ), val todoFilterBottomSheetState: Boolean = false, val selectedFilter: ToDoFilterType = ToDoFilterType.RECENT, val selectedItemList: List = listOf(), @@ -149,24 +150,24 @@ class TodoAddContract { data object ResetSelectedItemList : TodoAddReduce data class UpdateSelectedItemList( - val pieceId: Int + val pieceId: Int, ) : TodoAddReduce data class UpdateToDoFilterBottomSheetState( - val todoFilterBottomSheetState: Boolean + val todoFilterBottomSheetState: Boolean, ) : TodoAddReduce data class UpdateFilterType( - val selectedFilter: ToDoFilterType + val selectedFilter: ToDoFilterType, ) : TodoAddReduce data class DeleteSelectedItemList( - val pieceId: Int + val pieceId: Int, ) : TodoAddReduce data class UpdateCardState( val pieceId: Int, - val cardState: BbangZipCardState + val cardState: BbangZipCardState, ) : TodoAddReduce } @@ -179,4 +180,4 @@ class TodoAddContract { data class ShowTodoAddSnackBar(val message: String) : TodoAddSideEffect } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt index ea0fb965..dcc421bb 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt @@ -17,7 +17,7 @@ fun TodoAddRoute( snackBarHostState: SnackbarHostState, navigateToToDo: () -> Unit = {}, navigateToBack: () -> Unit = {}, - viewModel: TodoAddViewModel = hiltViewModel() + viewModel: TodoAddViewModel = hiltViewModel(), ) { val todoAddState by viewModel.uiState.collectAsStateWithLifecycle() val success by viewModel.success.collectAsStateWithLifecycle(initialValue = true) @@ -77,7 +77,7 @@ fun TodoAddRoute( }, onToDoCardClicked = { pieceId, cardState -> viewModel.setEvent(TodoAddContract.TodoAddEvent.OnToDoCardClicked(pieceId = pieceId, cardState = cardState)) - } + }, ) false -> diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt index 66916dbd..bf4a15a7 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt @@ -53,9 +53,10 @@ fun TodoAddScreen( onToDoCardClicked: (Int, BbangZipCardState) -> Unit = { _, _ -> }, ) { Box( - modifier = modifier - .fillMaxSize() - .background(color = BbangZipTheme.colors.staticWhite_FFFFFF) + modifier = + modifier + .fillMaxSize() + .background(color = BbangZipTheme.colors.staticWhite_FFFFFF), ) { Column { val scrollState = rememberLazyListState() @@ -68,22 +69,23 @@ fun TodoAddScreen( isShadowed = isShadowed, title = "", leadingIcon = R.drawable.ic_chevronleft_thick_small_24, - onLeadingIconClick = onBackIconClicked + onLeadingIconClick = onBackIconClicked, ) - Spacer(modifier = Modifier.height(32.dp)) + Spacer(modifier = Modifier.height(32.dp)) LazyColumn( - modifier = Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth(), - state = scrollState + modifier = + Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), + state = scrollState, ) { item { Text( text = stringResource(R.string.todo_add_title1), style = BbangZipTheme.typography.body1Bold, - color = BbangZipTheme.colors.labelAlternative_282119_61 + color = BbangZipTheme.colors.labelAlternative_282119_61, ) Spacer(modifier = Modifier.height(8.dp)) @@ -91,7 +93,7 @@ fun TodoAddScreen( Text( text = stringResource(R.string.todo_add_title2), style = BbangZipTheme.typography.title3Bold, - color = BbangZipTheme.colors.labelNormal_282119 + color = BbangZipTheme.colors.labelNormal_282119, ) Spacer(modifier = Modifier.height(32.dp)) @@ -99,39 +101,39 @@ fun TodoAddScreen( item { Row( - verticalAlignment = Alignment.CenterVertically + verticalAlignment = Alignment.CenterVertically, ) { Spacer(modifier = Modifier.width(8.dp)) - Text( text = "${todoAddState.selectedItemList.size} ", style = BbangZipTheme.typography.body2Bold, - color = BbangZipTheme.colors.labelNormal_282119 + color = BbangZipTheme.colors.labelNormal_282119, ) Text( - text = stringResource( - R.string.todo_add_count, - todoAddState.todoList.size - ), + text = + stringResource( + R.string.todo_add_count, + todoAddState.todoList.size, + ), style = BbangZipTheme.typography.body2Bold, - color = BbangZipTheme.colors.labelAlternative_282119_61 + color = BbangZipTheme.colors.labelAlternative_282119_61, ) Spacer(modifier = Modifier.weight(1f)) Box( - modifier = Modifier - .clip(CircleShape) - .clickable { onFilterIconClicked() }, - contentAlignment = Alignment.Center + modifier = + Modifier + .clip(CircleShape) + .clickable { onFilterIconClicked() }, + contentAlignment = Alignment.Center, ) { Icon( imageVector = ImageVector.vectorResource(R.drawable.ic_filter_default_24), contentDescription = null, modifier = Modifier.padding(8.dp), - tint = BbangZipTheme.colors.labelAlternative_282119_61 - + tint = BbangZipTheme.colors.labelAlternative_282119_61, ) } } @@ -143,30 +145,32 @@ fun TodoAddScreen( count = todoAddState.todoList.size, key = { index -> todoAddState.todoList[index].pieceId - }) { index -> + }, + ) { index -> ToDoCard( data = todoAddState.todoList[index], - modifier = Modifier.padding( vertical = 6.dp), + modifier = Modifier.padding(vertical = 6.dp), onClick = { - if (todoAddState.todoList[index].cardState == BbangZipCardState.CHECKED) + if (todoAddState.todoList[index].cardState == BbangZipCardState.CHECKED) { onToDoCardClicked( todoAddState.todoList[index].pieceId, - BbangZipCardState.CHECKABLE + BbangZipCardState.CHECKABLE, ) - else (todoAddState.todoList[index].cardState == BbangZipCardState.CHECKABLE) + } else { + (todoAddState.todoList[index].cardState == BbangZipCardState.CHECKABLE) + } onToDoCardClicked( todoAddState.todoList[index].pieceId, - BbangZipCardState.CHECKED + BbangZipCardState.CHECKED, ) - - } + }, ) } } } Column( modifier = Modifier.align(Alignment.BottomCenter), - horizontalAlignment = Alignment.CenterHorizontally + horizontalAlignment = Alignment.CenterHorizontally, ) { BbangZipSnackBarHost(snackBarHostState = todoAddSnackBarHostState) @@ -175,10 +179,11 @@ fun TodoAddScreen( bbangZipButtonSize = BbangZipButtonSize.Large, onClick = { onItemPlusButtonClicked() }, label = stringResource(R.string.todo_add_plus_button_label), - modifier = Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth() - .padding(bottom = 16.dp), + modifier = + Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth() + .padding(bottom = 16.dp), isEnable = todoAddState.selectedItemList.isNotEmpty(), trailingIcon = R.drawable.ic_plus_thick_24, ) @@ -188,6 +193,6 @@ fun TodoAddScreen( isBottomSheetVisible = todoAddState.todoFilterBottomSheetState, selectedItem = todoAddState.selectedFilter, onSelectedItemChanged = onFilterBottomSheetItemClicked, - onDismissRequest = onFilterBottomSheetDismissRequest + onDismissRequest = onFilterBottomSheetDismissRequest, ) -} \ No newline at end of file +} diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddViewModel.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddViewModel.kt index 2689095b..680d17fa 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddViewModel.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddViewModel.kt @@ -9,103 +9,115 @@ import javax.inject.Inject @HiltViewModel class TodoAddViewModel -@Inject -constructor( - savedStateHandle: SavedStateHandle, -) : BaseViewModel( - savedStateHandle = savedStateHandle, -) { - override fun createInitialState(savedState: Parcelable?): TodoAddContract.TodoAddState { - return savedState as? TodoAddContract.TodoAddState ?: TodoAddContract.TodoAddState() - } + @Inject + constructor( + savedStateHandle: SavedStateHandle, + ) : BaseViewModel( + savedStateHandle = savedStateHandle, + ) { + override fun createInitialState(savedState: Parcelable?): TodoAddContract.TodoAddState { + return savedState as? TodoAddContract.TodoAddState ?: TodoAddContract.TodoAddState() + } - override fun handleEvent(event: TodoAddContract.TodoAddEvent) { - when (event) { - TodoAddContract.TodoAddEvent.Initialize -> TODO() + override fun handleEvent(event: TodoAddContract.TodoAddEvent) { + when (event) { + TodoAddContract.TodoAddEvent.Initialize -> TODO() - TodoAddContract.TodoAddEvent.OnBackIconClicked -> { - updateState(TodoAddContract.TodoAddReduce.ResetSelectedItemList) - setSideEffect(TodoAddContract.TodoAddSideEffect.NavigateToBack) - } + TodoAddContract.TodoAddEvent.OnBackIconClicked -> { + updateState(TodoAddContract.TodoAddReduce.ResetSelectedItemList) + setSideEffect(TodoAddContract.TodoAddSideEffect.NavigateToBack) + } - TodoAddContract.TodoAddEvent.OnFilterBottomSheetDismissRequest -> updateState( - TodoAddContract.TodoAddReduce.UpdateToDoFilterBottomSheetState( - todoFilterBottomSheetState = false - ) - ) + TodoAddContract.TodoAddEvent.OnFilterBottomSheetDismissRequest -> + updateState( + TodoAddContract.TodoAddReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = false, + ), + ) - TodoAddContract.TodoAddEvent.OnFilterIconClicked -> updateState( - TodoAddContract.TodoAddReduce.UpdateToDoFilterBottomSheetState( - todoFilterBottomSheetState = true - ) - ) + TodoAddContract.TodoAddEvent.OnFilterIconClicked -> + updateState( + TodoAddContract.TodoAddReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = true, + ), + ) - is TodoAddContract.TodoAddEvent.OnFilterBottomSheetItemClicked -> { - updateState(TodoAddContract.TodoAddReduce.UpdateFilterType(selectedFilter = event.selectedFilterItem)) - updateState( - TodoAddContract.TodoAddReduce.UpdateToDoFilterBottomSheetState( - todoFilterBottomSheetState = false + is TodoAddContract.TodoAddEvent.OnFilterBottomSheetItemClicked -> { + updateState(TodoAddContract.TodoAddReduce.UpdateFilterType(selectedFilter = event.selectedFilterItem)) + updateState( + TodoAddContract.TodoAddReduce.UpdateToDoFilterBottomSheetState( + todoFilterBottomSheetState = false, + ), ) - ) - setSideEffect(TodoAddContract.TodoAddSideEffect.ShowTodoAddSnackBar("${event.selectedFilterItem.filter}으로 정렬했어요")) - //TODO 받아오고 다시 정렬해야됨 ㅋㅋ - } + setSideEffect(TodoAddContract.TodoAddSideEffect.ShowTodoAddSnackBar("${event.selectedFilterItem.filter}으로 정렬했어요")) + // TODO 받아오고 다시 정렬해야됨 ㅋㅋ + } - TodoAddContract.TodoAddEvent.OnItemPlusButtonClicked -> { - // TODO 서버로 보내기 - setSideEffect(TodoAddContract.TodoAddSideEffect.NavigateToToDo) - setSideEffect(TodoAddContract.TodoAddSideEffect.ShowSnackBar("오늘 할 공부를 추가했어요!")) - } + TodoAddContract.TodoAddEvent.OnItemPlusButtonClicked -> { + // TODO 서버로 보내기 + setSideEffect(TodoAddContract.TodoAddSideEffect.NavigateToToDo) + setSideEffect(TodoAddContract.TodoAddSideEffect.ShowSnackBar("오늘 할 공부를 추가했어요!")) + } - is TodoAddContract.TodoAddEvent.OnToDoCardClicked -> { - if (event.cardState == BbangZipCardState.CHECKED) { - updateState(TodoAddContract.TodoAddReduce.UpdateSelectedItemList(pieceId = event.pieceId)) - updateState( - TodoAddContract.TodoAddReduce.UpdateCardState( - pieceId = event.pieceId, - cardState = event.cardState + is TodoAddContract.TodoAddEvent.OnToDoCardClicked -> { + if (event.cardState == BbangZipCardState.CHECKED) { + updateState(TodoAddContract.TodoAddReduce.UpdateSelectedItemList(pieceId = event.pieceId)) + updateState( + TodoAddContract.TodoAddReduce.UpdateCardState( + pieceId = event.pieceId, + cardState = event.cardState, + ), ) - ) - } else { - updateState(TodoAddContract.TodoAddReduce.DeleteSelectedItemList(pieceId = event.pieceId)) - updateState( - TodoAddContract.TodoAddReduce.UpdateCardState( - pieceId = event.pieceId, - cardState = event.cardState + } else { + updateState(TodoAddContract.TodoAddReduce.DeleteSelectedItemList(pieceId = event.pieceId)) + updateState( + TodoAddContract.TodoAddReduce.UpdateCardState( + pieceId = event.pieceId, + cardState = event.cardState, + ), ) - ) + } } } } - } - override fun reduceState(state: TodoAddContract.TodoAddState, reduce: TodoAddContract.TodoAddReduce): TodoAddContract.TodoAddState { - return when (reduce) { - TodoAddContract.TodoAddReduce.ResetSelectedItemList -> state.copy( - selectedItemList = listOf() - ) + override fun reduceState( + state: TodoAddContract.TodoAddState, + reduce: TodoAddContract.TodoAddReduce, + ): TodoAddContract.TodoAddState { + return when (reduce) { + TodoAddContract.TodoAddReduce.ResetSelectedItemList -> + state.copy( + selectedItemList = listOf(), + ) - is TodoAddContract.TodoAddReduce.UpdateCardState -> state.copy( - todoList = state.todoList.map { item -> - if (item.pieceId == reduce.pieceId) item.copy(cardState = reduce.cardState) else item - } - ) + is TodoAddContract.TodoAddReduce.UpdateCardState -> + state.copy( + todoList = + state.todoList.map { item -> + if (item.pieceId == reduce.pieceId) item.copy(cardState = reduce.cardState) else item + }, + ) - is TodoAddContract.TodoAddReduce.UpdateFilterType -> state.copy( - selectedFilter = reduce.selectedFilter - ) + is TodoAddContract.TodoAddReduce.UpdateFilterType -> + state.copy( + selectedFilter = reduce.selectedFilter, + ) - is TodoAddContract.TodoAddReduce.UpdateSelectedItemList -> state.copy( - selectedItemList = state.selectedItemList.plus(reduce.pieceId) - ) + is TodoAddContract.TodoAddReduce.UpdateSelectedItemList -> + state.copy( + selectedItemList = state.selectedItemList.plus(reduce.pieceId), + ) - is TodoAddContract.TodoAddReduce.UpdateToDoFilterBottomSheetState -> state.copy( - todoFilterBottomSheetState = reduce.todoFilterBottomSheetState - ) + is TodoAddContract.TodoAddReduce.UpdateToDoFilterBottomSheetState -> + state.copy( + todoFilterBottomSheetState = reduce.todoFilterBottomSheetState, + ) - is TodoAddContract.TodoAddReduce.DeleteSelectedItemList -> state.copy( - selectedItemList = state.selectedItemList.minus(reduce.pieceId) - ) + is TodoAddContract.TodoAddReduce.DeleteSelectedItemList -> + state.copy( + selectedItemList = state.selectedItemList.minus(reduce.pieceId), + ) + } } } -} \ No newline at end of file diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/navigation/TodoAddNavigation.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/navigation/TodoAddNavigation.kt index d116c96f..e0097977 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/navigation/TodoAddNavigation.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/navigation/TodoAddNavigation.kt @@ -28,4 +28,4 @@ fun NavGraphBuilder.todoAddNavGraph( navigateToBack = navigateToBack, ) } -} \ No newline at end of file +} diff --git a/app/src/main/java/org/android/bbangzip/presentation/util/base/BaseViewModel.kt b/app/src/main/java/org/android/bbangzip/presentation/util/base/BaseViewModel.kt index d545f6aa..7cad25f1 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/util/base/BaseViewModel.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/util/base/BaseViewModel.kt @@ -4,7 +4,6 @@ import android.os.Parcelable import androidx.lifecycle.SavedStateHandle import androidx.lifecycle.ViewModel import androidx.lifecycle.viewModelScope -import androidx.lifecycle.viewmodel.compose.viewModel import kotlinx.coroutines.CoroutineExceptionHandler import kotlinx.coroutines.CoroutineScope import kotlinx.coroutines.Job diff --git a/app/src/main/java/org/android/bbangzip/presentation/util/modifier/ModifierExt.kt b/app/src/main/java/org/android/bbangzip/presentation/util/modifier/ModifierExt.kt index 3842e19e..81315053 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/util/modifier/ModifierExt.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/util/modifier/ModifierExt.kt @@ -7,7 +7,6 @@ import androidx.compose.foundation.gestures.detectTapGestures import androidx.compose.foundation.interaction.MutableInteractionSource import androidx.compose.foundation.interaction.collectIsPressedAsState import androidx.compose.foundation.shape.RoundedCornerShape -import androidx.compose.material.ripple.rememberRipple import androidx.compose.material3.ripple import androidx.compose.runtime.Composable import androidx.compose.runtime.getValue @@ -74,7 +73,7 @@ fun Modifier.applyFilterOnClick( .background(if (isPressed && !isDisabled) finalFilteredColor else baseColor, shape = RoundedCornerShape(size = radius)) .clickable( interactionSource = interactionSource, - indication = if(!isDisabled)rippleIndication else null, + indication = if (!isDisabled)rippleIndication else null, onClick = { onClick() }, ) } From b580e2234aded30a5cf46995564b7f7171acba92 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sun, 19 Jan 2025 17:37:58 +0900 Subject: [PATCH 32/40] =?UTF-8?q?[fix]=20#31=20bottomSheet=20dragHandle=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 --- .../component/bottomsheet/BbangZipBasicModalBottomSheet.kt | 2 ++ 1 file changed, 2 insertions(+) diff --git a/app/src/main/java/org/android/bbangzip/presentation/component/bottomsheet/BbangZipBasicModalBottomSheet.kt b/app/src/main/java/org/android/bbangzip/presentation/component/bottomsheet/BbangZipBasicModalBottomSheet.kt index f5b4876e..05133249 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/component/bottomsheet/BbangZipBasicModalBottomSheet.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/component/bottomsheet/BbangZipBasicModalBottomSheet.kt @@ -5,6 +5,7 @@ import androidx.compose.foundation.layout.ColumnScope import androidx.compose.foundation.layout.fillMaxWidth import androidx.compose.foundation.layout.padding import androidx.compose.foundation.shape.RoundedCornerShape +import androidx.compose.material3.BottomSheetDefaults import androidx.compose.material3.ExperimentalMaterial3Api import androidx.compose.material3.ModalBottomSheet import androidx.compose.material3.SheetState @@ -38,6 +39,7 @@ fun BbangZipBasicModalBottomSheet( ModalBottomSheet( onDismissRequest = onDismissRequest, sheetState = sheetState, + dragHandle = { BottomSheetDefaults.DragHandle(color = BbangZipTheme.colors.interactionInactive_D4D3D1) }, shape = RoundedCornerShape(topStart = 48.dp, topEnd = 48.dp), containerColor = BbangZipTheme.colors.backgroundNormal_FFFFFF, scrimColor = BbangZipTheme.colors.materialDimmer_282119_52, From 5cd9a69d4e5cf90e470601ebd8a4249993d8a8b7 Mon Sep 17 00:00:00 2001 From: beom84 Date: Sun, 19 Jan 2025 17:52:56 +0900 Subject: [PATCH 33/40] =?UTF-8?q?[fix]=20#31=20typo=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../org/android/bbangzip/ui/theme/Type.kt | 83 ++++++++++--------- 1 file changed, 44 insertions(+), 39 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/ui/theme/Type.kt b/app/src/main/java/org/android/bbangzip/ui/theme/Type.kt index b0124598..2a4906a4 100644 --- a/app/src/main/java/org/android/bbangzip/ui/theme/Type.kt +++ b/app/src/main/java/org/android/bbangzip/ui/theme/Type.kt @@ -2,6 +2,7 @@ package org.android.bbangzip.ui.theme import androidx.compose.runtime.Immutable import androidx.compose.runtime.staticCompositionLocalOf +import androidx.compose.ui.text.PlatformTextStyle import androidx.compose.ui.text.TextStyle import androidx.compose.ui.text.font.Font import androidx.compose.ui.text.font.FontFamily @@ -78,21 +79,21 @@ val defaultBbangZipTypography = lineHeight = 48.sp, letterSpacing = (-0.027).em, fontFamily = PretendardBold, - ), + ).withoutFontPadding(), title1Medium = TextStyle( fontSize = 36.sp, lineHeight = 48.sp, letterSpacing = (-0.027).em, fontFamily = PretendardMedium, - ), + ).withoutFontPadding(), title1Small = TextStyle( fontSize = 36.sp, lineHeight = 48.sp, letterSpacing = (-0.027).em, fontFamily = PretendardSmall, - ), + ).withoutFontPadding(), // Title 2 title2Bold = TextStyle( @@ -100,21 +101,21 @@ val defaultBbangZipTypography = lineHeight = 38.sp, letterSpacing = (-0.0236).em, fontFamily = PretendardBold, - ), + ).withoutFontPadding(), title2Medium = TextStyle( fontSize = 28.sp, lineHeight = 38.sp, letterSpacing = (-0.0236).em, fontFamily = PretendardMedium, - ), + ).withoutFontPadding(), title2Small = TextStyle( fontSize = 28.sp, lineHeight = 38.sp, letterSpacing = (-0.0236).em, fontFamily = PretendardSmall, - ), + ).withoutFontPadding(), // Title 3 title3Bold = TextStyle( @@ -122,21 +123,21 @@ val defaultBbangZipTypography = lineHeight = 32.sp, letterSpacing = (-0.023).em, fontFamily = PretendardBold, - ), + ).withoutFontPadding(), title3Medium = TextStyle( fontSize = 24.sp, lineHeight = 32.sp, letterSpacing = (-0.023).em, fontFamily = PretendardMedium, - ), + ).withoutFontPadding(), title3Small = TextStyle( fontSize = 24.sp, lineHeight = 32.sp, letterSpacing = (-0.023).em, fontFamily = PretendardSmall, - ), + ).withoutFontPadding(), // Heading 1 heading1Bold = TextStyle( @@ -144,21 +145,21 @@ val defaultBbangZipTypography = lineHeight = 30.sp, letterSpacing = (-0.0194).em, fontFamily = PretendardBold, - ), + ).withoutFontPadding(), heading1Medium = TextStyle( fontSize = 22.sp, lineHeight = 30.sp, letterSpacing = (-0.0194).em, fontFamily = PretendardMedium, - ), + ).withoutFontPadding(), heading1Small = TextStyle( fontSize = 22.sp, lineHeight = 30.sp, letterSpacing = (-0.0194).em, fontFamily = PretendardSmall, - ), + ).withoutFontPadding(), // Heading 2 heading2Bold = TextStyle( @@ -166,21 +167,21 @@ val defaultBbangZipTypography = lineHeight = 28.sp, letterSpacing = (-0.012).em, fontFamily = PretendardBold, - ), + ).withoutFontPadding(), heading2Medium = TextStyle( fontSize = 20.sp, lineHeight = 28.sp, letterSpacing = (-0.012).em, fontFamily = PretendardMedium, - ), + ).withoutFontPadding(), heading2Small = TextStyle( fontSize = 20.sp, lineHeight = 28.sp, letterSpacing = (-0.012).em, fontFamily = PretendardSmall, - ), + ).withoutFontPadding(), // Headline 1 headline1Bold = TextStyle( @@ -188,40 +189,40 @@ val defaultBbangZipTypography = lineHeight = 26.sp, letterSpacing = (-0.002).em, fontFamily = PretendardBold, - ), + ).withoutFontPadding(), headline1Medium = TextStyle( fontSize = 18.sp, lineHeight = 26.sp, letterSpacing = (-0.002).em, fontFamily = PretendardMedium, - ), + ).withoutFontPadding(), headline1Small = TextStyle( fontSize = 18.sp, lineHeight = 26.sp, letterSpacing = (-0.002).em, fontFamily = PretendardSmall, - ), + ).withoutFontPadding(), // Headline 2 headline2Bold = TextStyle( fontSize = 17.sp, lineHeight = 24.sp, fontFamily = PretendardBold, - ), + ).withoutFontPadding(), headline2Medium = TextStyle( fontSize = 17.sp, lineHeight = 24.sp, fontFamily = PretendardMedium, - ), + ).withoutFontPadding(), headline2Small = TextStyle( fontSize = 17.sp, lineHeight = 24.sp, fontFamily = PretendardSmall, - ), + ).withoutFontPadding(), // Body 1 body1Bold = TextStyle( @@ -229,21 +230,21 @@ val defaultBbangZipTypography = lineHeight = 24.sp, letterSpacing = 0.0057.em, fontFamily = PretendardBold, - ), + ).withoutFontPadding(), body1Medium = TextStyle( fontSize = 16.sp, lineHeight = 24.sp, letterSpacing = 0.0057.em, fontFamily = PretendardMedium, - ), + ).withoutFontPadding(), body1Small = TextStyle( fontSize = 16.sp, lineHeight = 24.sp, letterSpacing = 0.0057.em, fontFamily = PretendardSmall, - ), + ).withoutFontPadding(), // Body 2 body2Bold = TextStyle( @@ -251,21 +252,21 @@ val defaultBbangZipTypography = lineHeight = 22.sp, letterSpacing = 0.0096.em, fontFamily = PretendardBold, - ), + ).withoutFontPadding(), body2Medium = TextStyle( fontSize = 15.sp, lineHeight = 22.sp, letterSpacing = 0.0096.em, fontFamily = PretendardMedium, - ), + ).withoutFontPadding(), body2Small = TextStyle( fontSize = 15.sp, lineHeight = 22.sp, letterSpacing = 0.0096.em, fontFamily = PretendardSmall, - ), + ).withoutFontPadding(), // Label 1 label1Bold = TextStyle( @@ -273,21 +274,21 @@ val defaultBbangZipTypography = lineHeight = 20.sp, letterSpacing = 0.0145.em, fontFamily = PretendardBold, - ), + ).withoutFontPadding(), label1Medium = TextStyle( fontSize = 14.sp, lineHeight = 20.sp, letterSpacing = 0.0145.em, fontFamily = PretendardMedium, - ), + ).withoutFontPadding(), label1Small = TextStyle( fontSize = 14.sp, lineHeight = 20.sp, letterSpacing = 0.0145.em, fontFamily = PretendardSmall, - ), + ).withoutFontPadding(), // Label 2 label2Bold = TextStyle( @@ -295,21 +296,21 @@ val defaultBbangZipTypography = lineHeight = 18.sp, letterSpacing = 0.0194.em, fontFamily = PretendardBold, - ), + ).withoutFontPadding(), label2Medium = TextStyle( fontSize = 13.sp, lineHeight = 18.sp, letterSpacing = 0.0194.em, fontFamily = PretendardMedium, - ), + ).withoutFontPadding(), label2Small = TextStyle( fontSize = 13.sp, lineHeight = 18.sp, letterSpacing = 0.0194.em, fontFamily = PretendardSmall, - ), + ).withoutFontPadding(), // Caption 1 caption1Bold = TextStyle( @@ -317,21 +318,21 @@ val defaultBbangZipTypography = lineHeight = 16.sp, letterSpacing = 0.0252.em, fontFamily = PretendardBold, - ), + ).withoutFontPadding(), caption1Medium = TextStyle( fontSize = 12.sp, lineHeight = 16.sp, letterSpacing = 0.0252.em, fontFamily = PretendardMedium, - ), + ).withoutFontPadding(), caption1Small = TextStyle( fontSize = 12.sp, lineHeight = 16.sp, letterSpacing = 0.0252.em, fontFamily = PretendardSmall, - ), + ).withoutFontPadding(), // Caption 2 caption2Bold = TextStyle( @@ -339,21 +340,25 @@ val defaultBbangZipTypography = lineHeight = 14.sp, letterSpacing = 0.0311.em, fontFamily = PretendardBold, - ), + ).withoutFontPadding(), caption2Medium = TextStyle( fontSize = 11.sp, lineHeight = 14.sp, letterSpacing = 0.0311.em, fontFamily = PretendardMedium, - ), + ).withoutFontPadding(), caption2Small = TextStyle( fontSize = 11.sp, lineHeight = 14.sp, letterSpacing = 0.0311.em, fontFamily = PretendardSmall, - ), + ).withoutFontPadding(), ) val LocalBbangZipTypography = staticCompositionLocalOf { defaultBbangZipTypography } + +fun TextStyle.withoutFontPadding(): TextStyle { + return this.copy(platformStyle = PlatformTextStyle(includeFontPadding = false)) +} From eaee1fffc22da7602e904d57b73f77810be29012 Mon Sep 17 00:00:00 2001 From: beom84 Date: Mon, 20 Jan 2025 16:04:51 +0900 Subject: [PATCH 34/40] =?UTF-8?q?[feat]=20#31=20TodoScreen=20bottomPadding?= =?UTF-8?q?=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../bbangzip/presentation/ui/navigator/MainNavHost.kt | 1 + .../org/android/bbangzip/presentation/ui/todo/TodoRoute.kt | 3 +++ .../org/android/bbangzip/presentation/ui/todo/TodoScreen.kt | 6 +++++- .../presentation/ui/todo/navigation/TodoNavigation.kt | 3 +++ 4 files changed, 12 insertions(+), 1 deletion(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt index d1153fa5..f32bca79 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/MainNavHost.kt @@ -65,6 +65,7 @@ fun MainNavHost( todoNavGraph( snackBarHostState = snackBarHostState, + bottomPadding = padding, navigateToAddToDo = { navigator.navigateToToDoAdd() }, navigateToAddPendingToDo = { navigator.navigateToToDoAddPending() }, ) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt index 9e1cec44..4a28c888 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt @@ -1,5 +1,6 @@ package org.android.bbangzip.presentation.ui.todo +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.material3.SnackbarHostState import androidx.compose.material3.Text import androidx.compose.runtime.Composable @@ -17,6 +18,7 @@ import java.util.Locale @Composable fun TodoRoute( snackBarHostState: SnackbarHostState, + bottomPadding: PaddingValues, navigateToAddToDo: () -> Unit = {}, navigateToAddPendingToDo: () -> Unit = {}, viewModel: TodoViewModel = hiltViewModel(), @@ -52,6 +54,7 @@ fun TodoRoute( TodoScreen( todoState = todoState, todayDate = todayDate, + bottomPadding = bottomPadding, onAddPendingStudyButtonClicked = { viewModel.setEvent(TodoContract.TodoEvent.OnAddPendingStudyButtonClicked) }, diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt index c8391426..06ecb614 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt @@ -6,6 +6,7 @@ import androidx.compose.foundation.layout.Arrangement import androidx.compose.foundation.layout.Box import androidx.compose.foundation.layout.Column import androidx.compose.foundation.layout.ColumnScope +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.foundation.layout.Row import androidx.compose.foundation.layout.Spacer import androidx.compose.foundation.layout.fillMaxSize @@ -50,6 +51,7 @@ import org.android.bbangzip.ui.theme.BbangZipTheme fun TodoScreen( todoState: TodoContract.TodoState, todayDate: List, + bottomPadding : PaddingValues, modifier: Modifier = Modifier, onAddPendingStudyButtonClicked: () -> Unit = {}, onAddStudyButtonClicked: () -> Unit = {}, @@ -69,7 +71,8 @@ fun TodoScreen( modifier = modifier .fillMaxSize() - .padding(bottom = 74.dp) + .padding(bottomPadding) + .padding(bottom = 10.dp) .background(color = BbangZipTheme.colors.staticWhite_FFFFFF), ) { LazyColumn { @@ -722,5 +725,6 @@ fun TodoScreenMockPreview() { TodoScreen( todoState = mockTodoStates[0], todayDate = listOf("2025", "01", "18"), + bottomPadding = PaddingValues() ) } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt index 2f1944b6..4406bf19 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt @@ -1,5 +1,6 @@ package org.android.bbangzip.presentation.ui.todo.navigation +import androidx.compose.foundation.layout.PaddingValues import androidx.compose.material3.SnackbarHostState import androidx.navigation.NavController import androidx.navigation.NavGraphBuilder @@ -17,11 +18,13 @@ fun NavController.navigateTodo(navOptions: NavOptions) { fun NavGraphBuilder.todoNavGraph( snackBarHostState: SnackbarHostState, + bottomPadding :PaddingValues, navigateToAddToDo: () -> Unit, navigateToAddPendingToDo: () -> Unit = {}, ) { composable { TodoRoute( + bottomPadding = bottomPadding, snackBarHostState = snackBarHostState, navigateToAddToDo = navigateToAddToDo, navigateToAddPendingToDo = navigateToAddPendingToDo, From bb3770d864ba4887cd240a1ab8b0d15b5d05e1fa Mon Sep 17 00:00:00 2001 From: beom84 Date: Mon, 20 Jan 2025 16:15:49 +0900 Subject: [PATCH 35/40] =?UTF-8?q?[feat]=20#31=20PR=20=EC=BD=94=EB=93=9C?= =?UTF-8?q?=EB=A6=AC=EB=B7=B0=20=EC=A0=81=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/ui/todo/TodoContract.kt | 2 +- .../presentation/ui/todo/TodoScreen.kt | 153 +++++++++--------- .../pendingtodoadd/TodoAddPendingScreen.kt | 12 +- .../ui/todo/todoadd/TodoAddScreen.kt | 13 +- 4 files changed, 89 insertions(+), 91 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt index 7d03204a..75e17154 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoContract.kt @@ -131,7 +131,7 @@ class TodoContract { val selectedFilterItem: ToDoFilterType = ToDoFilterType.RECENT, val selectedItemList: List = listOf(), val revertCompleteBottomSheetState: Boolean = false, - val screenType: ToDoScreenType = ToDoScreenType.EMPTY, + val screenType: ToDoScreenType = ToDoScreenType.DEFAULT, ) : BaseContract.State, Parcelable { override fun toParcelable(): Parcelable = this } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt index 06ecb614..53dcd3ff 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt @@ -51,7 +51,7 @@ import org.android.bbangzip.ui.theme.BbangZipTheme fun TodoScreen( todoState: TodoContract.TodoState, todayDate: List, - bottomPadding : PaddingValues, + bottomPadding: PaddingValues, modifier: Modifier = Modifier, onAddPendingStudyButtonClicked: () -> Unit = {}, onAddStudyButtonClicked: () -> Unit = {}, @@ -69,11 +69,11 @@ fun TodoScreen( ) { Box( modifier = - modifier - .fillMaxSize() - .padding(bottomPadding) - .padding(bottom = 10.dp) - .background(color = BbangZipTheme.colors.staticWhite_FFFFFF), + modifier + .fillMaxSize() + .padding(bottomPadding) + .padding(bottom = 10.dp) + .background(color = BbangZipTheme.colors.staticWhite_FFFFFF), ) { LazyColumn { item { @@ -88,7 +88,20 @@ fun TodoScreen( if (todoState.screenType == ToDoScreenType.EMPTY) { item { - EmptyView(onAddStudyButtonClicked = onAddStudyButtonClicked) + Column(modifier = modifier.padding(horizontal = 16.dp)) { + EmptyView() + + Spacer(modifier = Modifier.height(16.dp)) + + BbangZipButton( + bbangZipButtonType = BbangZipButtonType.Solid, + bbangZipButtonSize = BbangZipButtonSize.Large, + onClick = { onAddStudyButtonClicked() }, + label = stringResource(R.string.btn_add_todo_label), + modifier = Modifier.fillMaxWidth(), + trailingIcon = R.drawable.ic_plus_thick_24, + ) + } } } @@ -123,18 +136,18 @@ fun TodoScreen( Row( modifier = - Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth(), + Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, ) { Spacer(modifier = Modifier.weight(1f)) Box( modifier = - Modifier - .clip(CircleShape) - .clickable { onCloseIconClicked() }, + Modifier + .clip(CircleShape) + .clickable { onCloseIconClicked() }, contentAlignment = Alignment.Center, ) { Icon( @@ -203,11 +216,11 @@ fun TodoScreen( onClick = { onItemDeleteButtonClicked() }, label = stringResource(R.string.todo_delete_screen_delete_button_text, todoState.selectedItemList.size), modifier = - Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth() - .align(Alignment.BottomCenter) - .padding(bottom = 6.dp), + Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth() + .align(Alignment.BottomCenter) + .padding(bottom = 6.dp), isEnable = todoState.selectedItemList.isNotEmpty(), trailingIcon = R.drawable.ic_plus_thick_24, ) @@ -240,8 +253,8 @@ fun DateMessageCard( ) { Box( modifier = - modifier - .fillMaxWidth(), + modifier + .fillMaxWidth(), ) { Column(modifier = Modifier.fillMaxWidth()) { Column( @@ -344,29 +357,29 @@ fun StudyCountText( ) { Column( modifier = - modifier - .padding(horizontal = 16.dp) - .fillMaxWidth() - .padding(start = 8.dp), + modifier + .padding(horizontal = 16.dp) + .fillMaxWidth() + .padding(start = 8.dp), ) { Text( text = - when { - completeCount > 0 && remainingCount != 0 -> stringResource(R.string.todo_complete_count_text, completeCount) - remainingCount == 0 -> stringResource(R.string.todo_complete_remaining_nothing_text) - else -> stringResource(R.string.todo_complete_nothing_text) - }, + when { + completeCount > 0 && remainingCount != 0 -> stringResource(R.string.todo_complete_count_text, completeCount) + remainingCount == 0 -> stringResource(R.string.todo_complete_remaining_nothing_text) + else -> stringResource(R.string.todo_complete_nothing_text) + }, style = BbangZipTheme.typography.label1Bold, color = BbangZipTheme.colors.labelAlternative_282119_61, ) Text( text = - if (remainingCount != 0) { - stringResource(R.string.todo_remaing_count_text, remainingCount) - } else { - stringResource(R.string.todo_remaining_nothing_text) - }, + if (remainingCount != 0) { + stringResource(R.string.todo_remaing_count_text, remainingCount) + } else { + stringResource(R.string.todo_remaining_nothing_text) + }, style = BbangZipTheme.typography.title3Bold, color = BbangZipTheme.colors.labelNormal_282119, ) @@ -381,18 +394,18 @@ fun DeleteAndFilterIcons( ) { Row( modifier = - modifier - .padding(horizontal = 16.dp) - .fillMaxWidth(), + modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, ) { Spacer(modifier = Modifier.weight(1f)) Box( modifier = - Modifier - .clip(CircleShape) - .clickable { onDeleteIconClicked() }, + Modifier + .clip(CircleShape) + .clickable { onDeleteIconClicked() }, contentAlignment = Alignment.Center, ) { Icon( @@ -405,9 +418,9 @@ fun DeleteAndFilterIcons( Box( modifier = - Modifier - .clip(CircleShape) - .clickable { onFilterIconClicked() }, + Modifier + .clip(CircleShape) + .clickable { onFilterIconClicked() }, contentAlignment = Alignment.Center, ) { Icon( @@ -423,30 +436,16 @@ fun DeleteAndFilterIcons( @Composable fun EmptyView( modifier: Modifier = Modifier, - onAddStudyButtonClicked: () -> Unit = {}, ) { - Column(modifier = modifier.padding(horizontal = 16.dp)) { - Box( - modifier = - Modifier - .fillMaxWidth() - .height(328.dp) - .background(color = BbangZipTheme.colors.backgroundAlternative_F5F5F5, shape = RoundedCornerShape(size = 32.dp)), - contentAlignment = Alignment.Center, - ) { - Text(text = "Empty View") - } - - Spacer(modifier = Modifier.height(16.dp)) - - BbangZipButton( - bbangZipButtonType = BbangZipButtonType.Solid, - bbangZipButtonSize = BbangZipButtonSize.Large, - onClick = { onAddStudyButtonClicked() }, - label = stringResource(R.string.btn_add_todo_label), - modifier = Modifier.fillMaxWidth(), - trailingIcon = R.drawable.ic_plus_thick_24, - ) + Box( + modifier = + modifier + .fillMaxWidth() + .height(328.dp) + .background(color = BbangZipTheme.colors.backgroundAlternative_F5F5F5, shape = RoundedCornerShape(size = 32.dp)), + contentAlignment = Alignment.Center, + ) { + Text(text = "Empty View") } } @@ -478,14 +477,14 @@ fun BbangZipToDoFilterPickerBottomSheet( Text( text = item.filter, modifier = - Modifier - .fillMaxWidth() - .applyFilterOnClick { onSelectedItemChanged(item) } - .background( - color = if (item != selectedItem) BbangZipTheme.colors.staticWhite_FFFFFF else BbangZipTheme.colors.fillStrong_68645E_16, - shape = RoundedCornerShape(16.dp), - ) - .padding(vertical = 8.dp), + Modifier + .fillMaxWidth() + .applyFilterOnClick { onSelectedItemChanged(item) } + .background( + color = if (item != selectedItem) BbangZipTheme.colors.staticWhite_FFFFFF else BbangZipTheme.colors.fillStrong_68645E_16, + shape = RoundedCornerShape(16.dp), + ) + .padding(vertical = 8.dp), textAlign = TextAlign.Center, style = BbangZipTheme.typography.body1Bold, color = BbangZipTheme.colors.labelNormal_282119, @@ -515,9 +514,9 @@ fun RevertCompleteBottomSheet( Text( text = bottomSheetTitle, modifier = - Modifier - .align(Alignment.CenterHorizontally) - .padding(vertical = 15.dp), + Modifier + .align(Alignment.CenterHorizontally) + .padding(vertical = 15.dp), style = BbangZipTheme.typography.headline1Bold, color = BbangZipTheme.colors.labelNeutral_282119_88, ) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt index 2695631a..d8bc1960 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt @@ -72,8 +72,6 @@ fun TodoAddPendingScreen( onLeadingIconClick = onBackIconClicked, ) - Spacer(modifier = Modifier.height(32.dp)) - LazyColumn( modifier = Modifier @@ -82,6 +80,8 @@ fun TodoAddPendingScreen( state = scrollState, ) { item { + Spacer(modifier = Modifier.height(32.dp)) + Text(text = stringResource(R.string.todo_pending_add_title1), style = BbangZipTheme.typography.body1Bold, color = BbangZipTheme.colors.labelAlternative_282119_61) Spacer(modifier = Modifier.height(8.dp)) @@ -138,11 +138,11 @@ fun TodoAddPendingScreen( ) } else { (todoAddState.todoList[index].cardState == BbangZipCardState.CHECKABLE) + onToDoCardClicked( + todoAddState.todoList[index].pieceId, + BbangZipCardState.CHECKED, + ) } - onToDoCardClicked( - todoAddState.todoList[index].pieceId, - BbangZipCardState.CHECKED, - ) }, ) } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt index bf4a15a7..48560814 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt @@ -67,13 +67,10 @@ fun TodoAddScreen( } BbangZipBaseTopBar( isShadowed = isShadowed, - title = "", leadingIcon = R.drawable.ic_chevronleft_thick_small_24, onLeadingIconClick = onBackIconClicked, ) - Spacer(modifier = Modifier.height(32.dp)) - LazyColumn( modifier = Modifier @@ -82,6 +79,8 @@ fun TodoAddScreen( state = scrollState, ) { item { + Spacer(modifier = Modifier.height(32.dp)) + Text( text = stringResource(R.string.todo_add_title1), style = BbangZipTheme.typography.body1Bold, @@ -158,11 +157,11 @@ fun TodoAddScreen( ) } else { (todoAddState.todoList[index].cardState == BbangZipCardState.CHECKABLE) + onToDoCardClicked( + todoAddState.todoList[index].pieceId, + BbangZipCardState.CHECKED, + ) } - onToDoCardClicked( - todoAddState.todoList[index].pieceId, - BbangZipCardState.CHECKED, - ) }, ) } From 2d19173078716ea78a6cdcc5e74904aef965f643 Mon Sep 17 00:00:00 2001 From: beom84 Date: Mon, 20 Jan 2025 16:21:20 +0900 Subject: [PATCH 36/40] =?UTF-8?q?[feat]=20#31=20Card=20shadow=20stroke=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 --- .../bbangzip/presentation/type/BbangZipCardType.kt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/type/BbangZipCardType.kt b/app/src/main/java/org/android/bbangzip/presentation/type/BbangZipCardType.kt index 47c23dbc..e0cde579 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/type/BbangZipCardType.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/type/BbangZipCardType.kt @@ -19,19 +19,19 @@ enum class BbangZipCardType( backgroundColor = defaultBbangZipColors.backgroundNormal_FFFFFF, borderColor = defaultBbangZipColors.lineAlternative_68645E_08, borderWidth = 1.dp, - shadowOptions = BbangZipShadowType.EMPHASIZE, + shadowOptions = BbangZipShadowType.NORMAL, ), CHECKABLE( backgroundColor = defaultBbangZipColors.backgroundAlternative_F5F5F5, borderColor = defaultBbangZipColors.lineAlternative_68645E_08, borderWidth = 1.dp, - shadowOptions = BbangZipShadowType.STRONG, + shadowOptions = BbangZipShadowType.EMPHASIZE, ), CHECKED( backgroundColor = defaultBbangZipColors.backgroundAlternative_F5F5F5, borderColor = defaultBbangZipColors.lineStrong_68645E_52, - borderWidth = 3.dp, - shadowOptions = BbangZipShadowType.EMPHASIZE, + borderWidth = 2.dp, + shadowOptions = BbangZipShadowType.NORMAL, ), COMPLETE( backgroundColor = defaultBbangZipColors.backgroundNormal_FFFFFF, From 1123fe5ce13f930ae2e8e892749cf61539bb14c0 Mon Sep 17 00:00:00 2001 From: beom84 Date: Mon, 20 Jan 2025 16:56:56 +0900 Subject: [PATCH 37/40] =?UTF-8?q?[fix]=20#31=20bottomBar=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 --- .../component/BottomNavigationBar.kt | 60 ++++++++++--------- 1 file changed, 31 insertions(+), 29 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/component/BottomNavigationBar.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/component/BottomNavigationBar.kt index d22440a9..9978ae2a 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/component/BottomNavigationBar.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/component/BottomNavigationBar.kt @@ -30,8 +30,9 @@ import androidx.compose.ui.unit.Dp import androidx.compose.ui.unit.dp import okhttp3.internal.toImmutableList import org.android.bbangzip.R +import org.android.bbangzip.presentation.type.BbangZipShadowType import org.android.bbangzip.presentation.type.BottomNavigationType -import org.android.bbangzip.presentation.util.modifier.dropShadow +import org.android.bbangzip.presentation.util.modifier.applyShadows import org.android.bbangzip.presentation.util.modifier.noRippleClickable import org.android.bbangzip.ui.theme.BBANGZIPTheme import org.android.bbangzip.ui.theme.BbangZipTheme @@ -51,23 +52,24 @@ fun BottomNavigationBar( ) { Box( modifier = - modifier - .fillMaxWidth() - .background(color = Color.Transparent) - .dropShadow( - offsetY = (-4).dp, - shape = RoundedCornerShape(topStart = 32.dp, topEnd = 32.dp), - ), + modifier + .applyShadows( + shadowType = BbangZipShadowType.EMPHASIZE_INVERSE, + shape = RoundedCornerShape(topStart = 32.dp, topEnd = 32.dp), + ) + .fillMaxWidth() + .background(color = Color.Transparent) + ) { Row( modifier = - Modifier - .fillMaxWidth() - .clip( - shape = RoundedCornerShape(topStart = 32.dp, topEnd = 32.dp), - ) - .background(color = BbangZipTheme.colors.backgroundNormal_FFFFFF) - .padding(top = 12.dp, bottom = 8.dp, start = 12.dp, end = 12.dp), + Modifier + .fillMaxWidth() + .clip( + shape = RoundedCornerShape(topStart = 32.dp, topEnd = 32.dp), + ) + .background(color = BbangZipTheme.colors.backgroundNormal_FFFFFF) + .padding(top = 12.dp, bottom = 8.dp, start = 12.dp, end = 12.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, ) { @@ -97,10 +99,10 @@ private fun BottomNavigationItem( ) { Column( modifier = - modifier - .noRippleClickable { - onBottomNaviBarItemSelected(bottomNaviType) - }, + modifier + .noRippleClickable { + onBottomNaviBarItemSelected(bottomNaviType) + }, horizontalAlignment = Alignment.CenterHorizontally, ) { Box( @@ -110,11 +112,11 @@ private fun BottomNavigationItem( imageVector = ImageVector.vectorResource(id = bottomNaviIcon), contentDescription = stringResource(id = R.string.app_name), tint = - if (isSelected) { - BbangZipTheme.colors.labelNormal_282119 - } else { - BbangZipTheme.colors.labelAssistive_282119_28 - }, + if (isSelected) { + BbangZipTheme.colors.labelNormal_282119 + } else { + BbangZipTheme.colors.labelAssistive_282119_28 + }, ) } @@ -123,11 +125,11 @@ private fun BottomNavigationItem( Text( text = stringResource(bottomNaviTitle), color = - if (isSelected) { - BbangZipTheme.colors.labelNormal_282119 - } else { - BbangZipTheme.colors.labelAssistive_282119_28 - }, + if (isSelected) { + BbangZipTheme.colors.labelNormal_282119 + } else { + BbangZipTheme.colors.labelAssistive_282119_28 + }, style = BbangZipTheme.typography.caption1Bold, ) } From 4fb4a2a5412e0a91913b924abb72cccfe3653802 Mon Sep 17 00:00:00 2001 From: beom84 Date: Mon, 20 Jan 2025 17:34:45 +0900 Subject: [PATCH 38/40] =?UTF-8?q?[fix]=20#31=20=EB=94=94=EC=9E=90=EC=9D=B8?= =?UTF-8?q?=20QA=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../presentation/ui/todo/TodoScreen.kt | 89 ++++++++++++------- .../pendingtodoadd/TodoAddPendingScreen.kt | 61 +++++++++---- .../ui/todo/todoadd/TodoAddScreen.kt | 4 + 3 files changed, 103 insertions(+), 51 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt index 53dcd3ff..76c1b081 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt @@ -71,8 +71,7 @@ fun TodoScreen( modifier = modifier .fillMaxSize() - .padding(bottomPadding) - .padding(bottom = 10.dp) + .padding(bottom = bottomPadding.calculateBottomPadding()) .background(color = BbangZipTheme.colors.staticWhite_FFFFFF), ) { LazyColumn { @@ -112,7 +111,7 @@ fun TodoScreen( completeCount = todoState.completeCount, ) - Spacer(Modifier.height(16.dp)) + Spacer(Modifier.height(8.dp)) DeleteAndFilterIcons( onDeleteIconClicked = onDeleteIconClicked, @@ -125,14 +124,21 @@ fun TodoScreen( if (todoState.screenType == ToDoScreenType.DELETE) { item { - Text( - text = stringResource(R.string.todo_delete_screen_text), - style = BbangZipTheme.typography.heading2Bold, - color = BbangZipTheme.colors.labelNormal_282119, - modifier = Modifier.padding(start = 24.dp), - ) + Box( + modifier = Modifier + .padding(start = 24.dp) + .fillMaxWidth() + .height(56.dp), + contentAlignment = Alignment.CenterStart + ) { + Text( + text = stringResource(R.string.todo_delete_screen_text), + style = BbangZipTheme.typography.heading2Bold, + color = BbangZipTheme.colors.labelNormal_282119, + ) + } - Spacer(Modifier.height(4.dp)) + Spacer(Modifier.height(8.dp)) Row( modifier = @@ -207,6 +213,16 @@ fun TodoScreen( }, ) } + + if (todoState.screenType == ToDoScreenType.DELETE) { + item { + Spacer(modifier = Modifier.height(72.dp)) + } + } + + item { + Spacer(modifier = Modifier.height(10.dp)) + } } } if (todoState.screenType == ToDoScreenType.DELETE) { @@ -220,7 +236,7 @@ fun TodoScreen( .padding(horizontal = 16.dp) .fillMaxWidth() .align(Alignment.BottomCenter) - .padding(bottom = 6.dp), + .padding(bottom = 16.dp), isEnable = todoState.selectedItemList.isNotEmpty(), trailingIcon = R.drawable.ic_plus_thick_24, ) @@ -355,34 +371,41 @@ fun StudyCountText( completeCount: Int, modifier: Modifier = Modifier, ) { - Column( + Box( modifier = modifier .padding(horizontal = 16.dp) .fillMaxWidth() - .padding(start = 8.dp), + .height(56.dp), + contentAlignment = Alignment.CenterStart ) { - Text( - text = - when { - completeCount > 0 && remainingCount != 0 -> stringResource(R.string.todo_complete_count_text, completeCount) - remainingCount == 0 -> stringResource(R.string.todo_complete_remaining_nothing_text) - else -> stringResource(R.string.todo_complete_nothing_text) - }, - style = BbangZipTheme.typography.label1Bold, - color = BbangZipTheme.colors.labelAlternative_282119_61, - ) + Column( + modifier = + Modifier + .padding(start = 8.dp), + ) { + Text( + text = + when { + completeCount > 0 && remainingCount != 0 -> stringResource(R.string.todo_complete_count_text, completeCount) + remainingCount == 0 -> stringResource(R.string.todo_complete_remaining_nothing_text) + else -> stringResource(R.string.todo_complete_nothing_text) + }, + style = BbangZipTheme.typography.label1Bold, + color = BbangZipTheme.colors.labelAlternative_282119_61, + ) - Text( - text = - if (remainingCount != 0) { - stringResource(R.string.todo_remaing_count_text, remainingCount) - } else { - stringResource(R.string.todo_remaining_nothing_text) - }, - style = BbangZipTheme.typography.title3Bold, - color = BbangZipTheme.colors.labelNormal_282119, - ) + Text( + text = + if (remainingCount != 0) { + stringResource(R.string.todo_remaing_count_text, remainingCount) + } else { + stringResource(R.string.todo_remaining_nothing_text) + }, + style = BbangZipTheme.typography.title3Bold, + color = BbangZipTheme.colors.labelNormal_282119, + ) + } } } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt index d8bc1960..cea3758f 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt @@ -4,6 +4,7 @@ import androidx.compose.foundation.background import androidx.compose.foundation.clickable 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 @@ -27,6 +28,7 @@ import androidx.compose.ui.draw.clip import androidx.compose.ui.graphics.vector.ImageVector import androidx.compose.ui.res.stringResource import androidx.compose.ui.res.vectorResource +import androidx.compose.ui.tooling.preview.Preview import androidx.compose.ui.unit.dp import org.android.bbangzip.R import org.android.bbangzip.presentation.component.button.BbangZipButton @@ -34,10 +36,14 @@ import org.android.bbangzip.presentation.component.card.BbangZipCardState import org.android.bbangzip.presentation.component.card.ToDoCard import org.android.bbangzip.presentation.component.snackbar.BbangZipSnackBarHost import org.android.bbangzip.presentation.component.topbar.BbangZipBaseTopBar +import org.android.bbangzip.presentation.model.card.ToDoCardModel import org.android.bbangzip.presentation.type.BbangZipButtonSize import org.android.bbangzip.presentation.type.BbangZipButtonType import org.android.bbangzip.presentation.type.ToDoFilterType +import org.android.bbangzip.presentation.type.ToDoScreenType import org.android.bbangzip.presentation.ui.todo.BbangZipToDoFilterPickerBottomSheet +import org.android.bbangzip.presentation.ui.todo.TodoContract +import org.android.bbangzip.presentation.ui.todo.TodoScreen import org.android.bbangzip.ui.theme.BbangZipTheme @Composable @@ -45,18 +51,18 @@ fun TodoAddPendingScreen( todoAddState: TodoAddPendingContract.TodoAddPendingState, todoAddSnackBarHostState: SnackbarHostState, modifier: Modifier = Modifier, - onBackIconClicked: () -> Unit, - onFilterBottomSheetDismissRequest: () -> Unit, - onFilterIconClicked: () -> Unit, - onFilterBottomSheetItemClicked: (ToDoFilterType) -> Unit, - onItemPlusButtonClicked: () -> Unit, + onBackIconClicked: () -> Unit = {}, + onFilterBottomSheetDismissRequest: () -> Unit = {}, + onFilterIconClicked: () -> Unit = {}, + onFilterBottomSheetItemClicked: (ToDoFilterType) -> Unit = {}, + onItemPlusButtonClicked: () -> Unit = {}, onToDoCardClicked: (Int, BbangZipCardState) -> Unit = { _, _ -> }, ) { Box( modifier = - modifier - .fillMaxSize() - .background(color = BbangZipTheme.colors.staticWhite_FFFFFF), + modifier + .fillMaxSize() + .background(color = BbangZipTheme.colors.staticWhite_FFFFFF), ) { Column { val scrollState = rememberLazyListState() @@ -74,9 +80,9 @@ fun TodoAddPendingScreen( LazyColumn( modifier = - Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth(), + Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), state = scrollState, ) { item { @@ -104,9 +110,9 @@ fun TodoAddPendingScreen( Box( modifier = - Modifier - .clip(CircleShape) - .clickable { onFilterIconClicked() }, + Modifier + .clip(CircleShape) + .clickable { onFilterIconClicked() }, contentAlignment = Alignment.Center, ) { Icon( @@ -146,6 +152,10 @@ fun TodoAddPendingScreen( }, ) } + + item { + Spacer(modifier= Modifier.height(82.dp)) + } } } Column( @@ -160,10 +170,10 @@ fun TodoAddPendingScreen( onClick = { onItemPlusButtonClicked() }, label = stringResource(R.string.todo_add_plus_button_label), modifier = - Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth() - .padding(bottom = 16.dp), + Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth() + .padding(bottom = 16.dp), isEnable = todoAddState.selectedItemList.isNotEmpty(), trailingIcon = R.drawable.ic_plus_thick_24, ) @@ -176,3 +186,18 @@ fun TodoAddPendingScreen( onDismissRequest = onFilterBottomSheetDismissRequest, ) } + +@Preview +@Composable +private fun PendingPreview() { + + + val mockTodoStates = + TodoAddPendingContract.TodoAddPendingState() + + + TodoAddPendingScreen( + todoAddState = mockTodoStates, + todoAddSnackBarHostState = remember { SnackbarHostState() } + ) +} \ No newline at end of file diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt index 48560814..0b4503fb 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt @@ -165,6 +165,10 @@ fun TodoAddScreen( }, ) } + + item { + Spacer(modifier= Modifier.height(82.dp)) + } } } Column( From 5cfac5f99c7bef5284c999f82318ac98c9f00e21 Mon Sep 17 00:00:00 2001 From: beom84 Date: Mon, 20 Jan 2025 17:35:16 +0900 Subject: [PATCH 39/40] =?UTF-8?q?[chore]=20#31=20ktlint=20=EC=A0=81?= =?UTF-8?q?=EC=9A=A9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../component/BottomNavigationBar.kt | 57 ++++---- .../presentation/ui/todo/TodoScreen.kt | 129 +++++++++--------- .../ui/todo/navigation/TodoNavigation.kt | 2 +- .../pendingtodoadd/TodoAddPendingScreen.kt | 40 +++--- .../ui/todo/todoadd/TodoAddScreen.kt | 2 +- 5 files changed, 111 insertions(+), 119 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/component/BottomNavigationBar.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/component/BottomNavigationBar.kt index 9978ae2a..461bc553 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/component/BottomNavigationBar.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/navigator/component/BottomNavigationBar.kt @@ -52,24 +52,23 @@ fun BottomNavigationBar( ) { Box( modifier = - modifier - .applyShadows( - shadowType = BbangZipShadowType.EMPHASIZE_INVERSE, - shape = RoundedCornerShape(topStart = 32.dp, topEnd = 32.dp), - ) - .fillMaxWidth() - .background(color = Color.Transparent) - + modifier + .applyShadows( + shadowType = BbangZipShadowType.EMPHASIZE_INVERSE, + shape = RoundedCornerShape(topStart = 32.dp, topEnd = 32.dp), + ) + .fillMaxWidth() + .background(color = Color.Transparent), ) { Row( modifier = - Modifier - .fillMaxWidth() - .clip( - shape = RoundedCornerShape(topStart = 32.dp, topEnd = 32.dp), - ) - .background(color = BbangZipTheme.colors.backgroundNormal_FFFFFF) - .padding(top = 12.dp, bottom = 8.dp, start = 12.dp, end = 12.dp), + Modifier + .fillMaxWidth() + .clip( + shape = RoundedCornerShape(topStart = 32.dp, topEnd = 32.dp), + ) + .background(color = BbangZipTheme.colors.backgroundNormal_FFFFFF) + .padding(top = 12.dp, bottom = 8.dp, start = 12.dp, end = 12.dp), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, ) { @@ -99,10 +98,10 @@ private fun BottomNavigationItem( ) { Column( modifier = - modifier - .noRippleClickable { - onBottomNaviBarItemSelected(bottomNaviType) - }, + modifier + .noRippleClickable { + onBottomNaviBarItemSelected(bottomNaviType) + }, horizontalAlignment = Alignment.CenterHorizontally, ) { Box( @@ -112,11 +111,11 @@ private fun BottomNavigationItem( imageVector = ImageVector.vectorResource(id = bottomNaviIcon), contentDescription = stringResource(id = R.string.app_name), tint = - if (isSelected) { - BbangZipTheme.colors.labelNormal_282119 - } else { - BbangZipTheme.colors.labelAssistive_282119_28 - }, + if (isSelected) { + BbangZipTheme.colors.labelNormal_282119 + } else { + BbangZipTheme.colors.labelAssistive_282119_28 + }, ) } @@ -125,11 +124,11 @@ private fun BottomNavigationItem( Text( text = stringResource(bottomNaviTitle), color = - if (isSelected) { - BbangZipTheme.colors.labelNormal_282119 - } else { - BbangZipTheme.colors.labelAssistive_282119_28 - }, + if (isSelected) { + BbangZipTheme.colors.labelNormal_282119 + } else { + BbangZipTheme.colors.labelAssistive_282119_28 + }, style = BbangZipTheme.typography.caption1Bold, ) } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt index 76c1b081..2b194c71 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoScreen.kt @@ -69,10 +69,10 @@ fun TodoScreen( ) { Box( modifier = - modifier - .fillMaxSize() - .padding(bottom = bottomPadding.calculateBottomPadding()) - .background(color = BbangZipTheme.colors.staticWhite_FFFFFF), + modifier + .fillMaxSize() + .padding(bottom = bottomPadding.calculateBottomPadding()) + .background(color = BbangZipTheme.colors.staticWhite_FFFFFF), ) { LazyColumn { item { @@ -125,11 +125,12 @@ fun TodoScreen( if (todoState.screenType == ToDoScreenType.DELETE) { item { Box( - modifier = Modifier - .padding(start = 24.dp) - .fillMaxWidth() - .height(56.dp), - contentAlignment = Alignment.CenterStart + modifier = + Modifier + .padding(start = 24.dp) + .fillMaxWidth() + .height(56.dp), + contentAlignment = Alignment.CenterStart, ) { Text( text = stringResource(R.string.todo_delete_screen_text), @@ -142,18 +143,18 @@ fun TodoScreen( Row( modifier = - Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth(), + Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, ) { Spacer(modifier = Modifier.weight(1f)) Box( modifier = - Modifier - .clip(CircleShape) - .clickable { onCloseIconClicked() }, + Modifier + .clip(CircleShape) + .clickable { onCloseIconClicked() }, contentAlignment = Alignment.Center, ) { Icon( @@ -232,11 +233,11 @@ fun TodoScreen( onClick = { onItemDeleteButtonClicked() }, label = stringResource(R.string.todo_delete_screen_delete_button_text, todoState.selectedItemList.size), modifier = - Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth() - .align(Alignment.BottomCenter) - .padding(bottom = 16.dp), + Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth() + .align(Alignment.BottomCenter) + .padding(bottom = 16.dp), isEnable = todoState.selectedItemList.isNotEmpty(), trailingIcon = R.drawable.ic_plus_thick_24, ) @@ -269,8 +270,8 @@ fun DateMessageCard( ) { Box( modifier = - modifier - .fillMaxWidth(), + modifier + .fillMaxWidth(), ) { Column(modifier = Modifier.fillMaxWidth()) { Column( @@ -373,35 +374,35 @@ fun StudyCountText( ) { Box( modifier = - modifier - .padding(horizontal = 16.dp) - .fillMaxWidth() - .height(56.dp), - contentAlignment = Alignment.CenterStart + modifier + .padding(horizontal = 16.dp) + .fillMaxWidth() + .height(56.dp), + contentAlignment = Alignment.CenterStart, ) { Column( modifier = - Modifier - .padding(start = 8.dp), + Modifier + .padding(start = 8.dp), ) { Text( text = - when { - completeCount > 0 && remainingCount != 0 -> stringResource(R.string.todo_complete_count_text, completeCount) - remainingCount == 0 -> stringResource(R.string.todo_complete_remaining_nothing_text) - else -> stringResource(R.string.todo_complete_nothing_text) - }, + when { + completeCount > 0 && remainingCount != 0 -> stringResource(R.string.todo_complete_count_text, completeCount) + remainingCount == 0 -> stringResource(R.string.todo_complete_remaining_nothing_text) + else -> stringResource(R.string.todo_complete_nothing_text) + }, style = BbangZipTheme.typography.label1Bold, color = BbangZipTheme.colors.labelAlternative_282119_61, ) Text( text = - if (remainingCount != 0) { - stringResource(R.string.todo_remaing_count_text, remainingCount) - } else { - stringResource(R.string.todo_remaining_nothing_text) - }, + if (remainingCount != 0) { + stringResource(R.string.todo_remaing_count_text, remainingCount) + } else { + stringResource(R.string.todo_remaining_nothing_text) + }, style = BbangZipTheme.typography.title3Bold, color = BbangZipTheme.colors.labelNormal_282119, ) @@ -417,18 +418,18 @@ fun DeleteAndFilterIcons( ) { Row( modifier = - modifier - .padding(horizontal = 16.dp) - .fillMaxWidth(), + modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, ) { Spacer(modifier = Modifier.weight(1f)) Box( modifier = - Modifier - .clip(CircleShape) - .clickable { onDeleteIconClicked() }, + Modifier + .clip(CircleShape) + .clickable { onDeleteIconClicked() }, contentAlignment = Alignment.Center, ) { Icon( @@ -441,9 +442,9 @@ fun DeleteAndFilterIcons( Box( modifier = - Modifier - .clip(CircleShape) - .clickable { onFilterIconClicked() }, + Modifier + .clip(CircleShape) + .clickable { onFilterIconClicked() }, contentAlignment = Alignment.Center, ) { Icon( @@ -462,10 +463,10 @@ fun EmptyView( ) { Box( modifier = - modifier - .fillMaxWidth() - .height(328.dp) - .background(color = BbangZipTheme.colors.backgroundAlternative_F5F5F5, shape = RoundedCornerShape(size = 32.dp)), + modifier + .fillMaxWidth() + .height(328.dp) + .background(color = BbangZipTheme.colors.backgroundAlternative_F5F5F5, shape = RoundedCornerShape(size = 32.dp)), contentAlignment = Alignment.Center, ) { Text(text = "Empty View") @@ -500,14 +501,14 @@ fun BbangZipToDoFilterPickerBottomSheet( Text( text = item.filter, modifier = - Modifier - .fillMaxWidth() - .applyFilterOnClick { onSelectedItemChanged(item) } - .background( - color = if (item != selectedItem) BbangZipTheme.colors.staticWhite_FFFFFF else BbangZipTheme.colors.fillStrong_68645E_16, - shape = RoundedCornerShape(16.dp), - ) - .padding(vertical = 8.dp), + Modifier + .fillMaxWidth() + .applyFilterOnClick { onSelectedItemChanged(item) } + .background( + color = if (item != selectedItem) BbangZipTheme.colors.staticWhite_FFFFFF else BbangZipTheme.colors.fillStrong_68645E_16, + shape = RoundedCornerShape(16.dp), + ) + .padding(vertical = 8.dp), textAlign = TextAlign.Center, style = BbangZipTheme.typography.body1Bold, color = BbangZipTheme.colors.labelNormal_282119, @@ -537,9 +538,9 @@ fun RevertCompleteBottomSheet( Text( text = bottomSheetTitle, modifier = - Modifier - .align(Alignment.CenterHorizontally) - .padding(vertical = 15.dp), + Modifier + .align(Alignment.CenterHorizontally) + .padding(vertical = 15.dp), style = BbangZipTheme.typography.headline1Bold, color = BbangZipTheme.colors.labelNeutral_282119_88, ) @@ -747,6 +748,6 @@ fun TodoScreenMockPreview() { TodoScreen( todoState = mockTodoStates[0], todayDate = listOf("2025", "01", "18"), - bottomPadding = PaddingValues() + bottomPadding = PaddingValues(), ) } diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt index 4406bf19..80ae251d 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/navigation/TodoNavigation.kt @@ -18,7 +18,7 @@ fun NavController.navigateTodo(navOptions: NavOptions) { fun NavGraphBuilder.todoNavGraph( snackBarHostState: SnackbarHostState, - bottomPadding :PaddingValues, + bottomPadding: PaddingValues, navigateToAddToDo: () -> Unit, navigateToAddPendingToDo: () -> Unit = {}, ) { diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt index cea3758f..5139face 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingScreen.kt @@ -4,7 +4,6 @@ import androidx.compose.foundation.background import androidx.compose.foundation.clickable 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 @@ -36,14 +35,10 @@ import org.android.bbangzip.presentation.component.card.BbangZipCardState import org.android.bbangzip.presentation.component.card.ToDoCard import org.android.bbangzip.presentation.component.snackbar.BbangZipSnackBarHost import org.android.bbangzip.presentation.component.topbar.BbangZipBaseTopBar -import org.android.bbangzip.presentation.model.card.ToDoCardModel import org.android.bbangzip.presentation.type.BbangZipButtonSize import org.android.bbangzip.presentation.type.BbangZipButtonType import org.android.bbangzip.presentation.type.ToDoFilterType -import org.android.bbangzip.presentation.type.ToDoScreenType import org.android.bbangzip.presentation.ui.todo.BbangZipToDoFilterPickerBottomSheet -import org.android.bbangzip.presentation.ui.todo.TodoContract -import org.android.bbangzip.presentation.ui.todo.TodoScreen import org.android.bbangzip.ui.theme.BbangZipTheme @Composable @@ -60,9 +55,9 @@ fun TodoAddPendingScreen( ) { Box( modifier = - modifier - .fillMaxSize() - .background(color = BbangZipTheme.colors.staticWhite_FFFFFF), + modifier + .fillMaxSize() + .background(color = BbangZipTheme.colors.staticWhite_FFFFFF), ) { Column { val scrollState = rememberLazyListState() @@ -80,9 +75,9 @@ fun TodoAddPendingScreen( LazyColumn( modifier = - Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth(), + Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth(), state = scrollState, ) { item { @@ -110,9 +105,9 @@ fun TodoAddPendingScreen( Box( modifier = - Modifier - .clip(CircleShape) - .clickable { onFilterIconClicked() }, + Modifier + .clip(CircleShape) + .clickable { onFilterIconClicked() }, contentAlignment = Alignment.Center, ) { Icon( @@ -154,7 +149,7 @@ fun TodoAddPendingScreen( } item { - Spacer(modifier= Modifier.height(82.dp)) + Spacer(modifier = Modifier.height(82.dp)) } } } @@ -170,10 +165,10 @@ fun TodoAddPendingScreen( onClick = { onItemPlusButtonClicked() }, label = stringResource(R.string.todo_add_plus_button_label), modifier = - Modifier - .padding(horizontal = 16.dp) - .fillMaxWidth() - .padding(bottom = 16.dp), + Modifier + .padding(horizontal = 16.dp) + .fillMaxWidth() + .padding(bottom = 16.dp), isEnable = todoAddState.selectedItemList.isNotEmpty(), trailingIcon = R.drawable.ic_plus_thick_24, ) @@ -190,14 +185,11 @@ fun TodoAddPendingScreen( @Preview @Composable private fun PendingPreview() { - - val mockTodoStates = TodoAddPendingContract.TodoAddPendingState() - TodoAddPendingScreen( todoAddState = mockTodoStates, - todoAddSnackBarHostState = remember { SnackbarHostState() } + todoAddSnackBarHostState = remember { SnackbarHostState() }, ) -} \ No newline at end of file +} diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt index 0b4503fb..adab8349 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddScreen.kt @@ -167,7 +167,7 @@ fun TodoAddScreen( } item { - Spacer(modifier= Modifier.height(82.dp)) + Spacer(modifier = Modifier.height(82.dp)) } } } From d27ec994ea18debb2c99776bcd174be03ee3d890 Mon Sep 17 00:00:00 2001 From: beom84 Date: Mon, 20 Jan 2025 17:38:13 +0900 Subject: [PATCH 40/40] =?UTF-8?q?[chore]=20#31=20viewmodel=20success=20val?= =?UTF-8?q?ue=20=EC=88=98=EC=A0=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt | 2 +- .../presentation/ui/todo/pendingtodoadd/TodoAddPendingRoute.kt | 2 +- .../bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt index 4a28c888..4857eeef 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/TodoRoute.kt @@ -24,7 +24,7 @@ fun TodoRoute( viewModel: TodoViewModel = hiltViewModel(), ) { val todoState by viewModel.uiState.collectAsStateWithLifecycle() - val success by viewModel.success.collectAsStateWithLifecycle(initialValue = true) + val success by viewModel.success.collectAsStateWithLifecycle(initialValue = false) val todayDate = LocalDateTime.now().format(DateTimeFormatter.ofPattern("MM-dd-E").withLocale(Locale.forLanguageTag("ko"))).split("-") LaunchedEffect(viewModel.uiSideEffect) { diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingRoute.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingRoute.kt index 525e47fa..996e2123 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingRoute.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/pendingtodoadd/TodoAddPendingRoute.kt @@ -20,7 +20,7 @@ fun TodoAddPendingRoute( viewModel: TodoAddPendingViewModel = hiltViewModel(), ) { val todoAddPendingState by viewModel.uiState.collectAsStateWithLifecycle() - val success by viewModel.success.collectAsStateWithLifecycle(initialValue = true) + val success by viewModel.success.collectAsStateWithLifecycle(initialValue = false) val todoAddsSnackBarHostState = remember { SnackbarHostState() } LaunchedEffect(viewModel.uiSideEffect) { diff --git a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt index dcc421bb..4fc91755 100644 --- a/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt +++ b/app/src/main/java/org/android/bbangzip/presentation/ui/todo/todoadd/TodoAddRoute.kt @@ -20,7 +20,7 @@ fun TodoAddRoute( viewModel: TodoAddViewModel = hiltViewModel(), ) { val todoAddState by viewModel.uiState.collectAsStateWithLifecycle() - val success by viewModel.success.collectAsStateWithLifecycle(initialValue = true) + val success by viewModel.success.collectAsStateWithLifecycle(initialValue = false) val todoAddsSnackBarHostState = remember { SnackbarHostState() } LaunchedEffect(viewModel.uiSideEffect) {