diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 4f128007..c4536515 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -139,6 +139,11 @@
android:exported="false"
android:screenOrientation="portrait" />
+
+
@@ -50,4 +52,10 @@ interface TodoDataSource {
tripId : Long
): BaseResponse
+ suspend fun patchTodoData(
+ tripId: Long,
+ todoId: Long,
+ request: TodoChangeRequestDto
+ ): NonDataBaseResponse
+
}
diff --git a/data/src/main/java/com/going/data/datasourceImpl/TodoDataSourceImpl.kt b/data/src/main/java/com/going/data/datasourceImpl/TodoDataSourceImpl.kt
index d6e78607..dd60993d 100644
--- a/data/src/main/java/com/going/data/datasourceImpl/TodoDataSourceImpl.kt
+++ b/data/src/main/java/com/going/data/datasourceImpl/TodoDataSourceImpl.kt
@@ -3,6 +3,7 @@ package com.going.data.datasourceImpl
import com.going.data.datasource.TodoDataSource
import com.going.data.dto.BaseResponse
import com.going.data.dto.NonDataBaseResponse
+import com.going.data.dto.request.TodoChangeRequestDto
import com.going.data.dto.request.TodoCreateRequestDto
import com.going.data.dto.response.CheckFriendsResponseDto
import com.going.data.dto.response.MyTripInfoResponseDto
@@ -35,9 +36,10 @@ class TodoDataSourceImpl @Inject constructor(
todoService.deleteTodo(todoId)
override suspend fun getTodoDetailData(
+ tripId: Long,
todoId: Long
): BaseResponse =
- todoService.getTodoDetail(todoId)
+ todoService.getTodoDetail(tripId, todoId)
override suspend fun getMyTripInfo(
tripId: Long
@@ -64,4 +66,11 @@ class TodoDataSourceImpl @Inject constructor(
): BaseResponse =
todoService.getFriendsList(tripId)
+ override suspend fun patchTodoData(
+ tripId: Long,
+ todoId: Long,
+ request: TodoChangeRequestDto
+ ): NonDataBaseResponse =
+ todoService.patchTodo(tripId, todoId, request)
+
}
diff --git a/data/src/main/java/com/going/data/dto/request/TodoChangeRequestDto.kt b/data/src/main/java/com/going/data/dto/request/TodoChangeRequestDto.kt
new file mode 100644
index 00000000..c70c04c6
--- /dev/null
+++ b/data/src/main/java/com/going/data/dto/request/TodoChangeRequestDto.kt
@@ -0,0 +1,22 @@
+package com.going.data.dto.request
+
+import com.going.domain.entity.request.TodoChangeRequestModel
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class TodoChangeRequestDto(
+ @SerialName("title")
+ val title: String,
+ @SerialName("endDate")
+ val endDate: String,
+ @SerialName("allocators")
+ val allocators: List,
+ @SerialName("memo")
+ val memo: String?,
+ @SerialName("secret")
+ val secret: Boolean
+)
+
+fun TodoChangeRequestModel.toTodoChangeRequestDto(): TodoChangeRequestDto =
+ TodoChangeRequestDto(title, endDate, allocators, memo, secret)
\ No newline at end of file
diff --git a/data/src/main/java/com/going/data/dto/response/TodoAllocatorResponseDto.kt b/data/src/main/java/com/going/data/dto/response/TodoAllocatorResponseDto.kt
index 378227fa..d3a17c81 100644
--- a/data/src/main/java/com/going/data/dto/response/TodoAllocatorResponseDto.kt
+++ b/data/src/main/java/com/going/data/dto/response/TodoAllocatorResponseDto.kt
@@ -6,11 +6,15 @@ import kotlinx.serialization.Serializable
@Serializable
data class TodoAllocatorResponseDto(
+ @SerialName("participantId")
+ val participantId: Long,
@SerialName("name")
val name: String,
@SerialName("isOwner")
- val isOwner: Boolean
+ val isOwner: Boolean,
+ @SerialName("isAllocated")
+ val isAllocated: Boolean
) {
fun toTodoAllocatorModel() =
- TodoAllocatorModel(name, isOwner)
+ TodoAllocatorModel(participantId, name, isOwner, isAllocated)
}
\ No newline at end of file
diff --git a/data/src/main/java/com/going/data/dto/response/TodoListAllocatorResponseDto.kt b/data/src/main/java/com/going/data/dto/response/TodoListAllocatorResponseDto.kt
new file mode 100644
index 00000000..1b9d1c7b
--- /dev/null
+++ b/data/src/main/java/com/going/data/dto/response/TodoListAllocatorResponseDto.kt
@@ -0,0 +1,16 @@
+package com.going.data.dto.response
+
+import com.going.domain.entity.response.TodoListAllocatorModel
+import kotlinx.serialization.SerialName
+import kotlinx.serialization.Serializable
+
+@Serializable
+data class TodoListAllocatorResponseDto(
+ @SerialName("name")
+ val name: String,
+ @SerialName("isOwner")
+ val isOwner: Boolean
+) {
+ fun toTodoListAllocatorModel() =
+ TodoListAllocatorModel(name, isOwner)
+}
\ No newline at end of file
diff --git a/data/src/main/java/com/going/data/dto/response/TodoResponseDto.kt b/data/src/main/java/com/going/data/dto/response/TodoResponseDto.kt
index a3d921ab..08f31aa5 100644
--- a/data/src/main/java/com/going/data/dto/response/TodoResponseDto.kt
+++ b/data/src/main/java/com/going/data/dto/response/TodoResponseDto.kt
@@ -1,6 +1,5 @@
package com.going.data.dto.response
-import com.going.domain.entity.response.TodoAllocatorModel
import com.going.domain.entity.response.TodoModel
import kotlinx.serialization.SerialName
import kotlinx.serialization.Serializable
@@ -14,10 +13,10 @@ data class TodoResponseDto(
@SerialName("endDate")
val endDate: String,
@SerialName("allocators")
- val allocators: List,
+ val allocators: List,
@SerialName("secret")
val secret: Boolean
) {
fun toTodoModel() =
- TodoModel(todoId, title, endDate, allocators.map { it.toTodoAllocatorModel() }, secret)
+ TodoModel(todoId, title, endDate, allocators.map { it.toTodoListAllocatorModel() }, secret)
}
diff --git a/data/src/main/java/com/going/data/repositoryImpl/TodoRepositoryImpl.kt b/data/src/main/java/com/going/data/repositoryImpl/TodoRepositoryImpl.kt
index d7e3b77f..f1d2db98 100644
--- a/data/src/main/java/com/going/data/repositoryImpl/TodoRepositoryImpl.kt
+++ b/data/src/main/java/com/going/data/repositoryImpl/TodoRepositoryImpl.kt
@@ -1,7 +1,9 @@
package com.going.data.repositoryImpl
import com.going.data.datasource.TodoDataSource
+import com.going.data.dto.request.toTodoChangeRequestDto
import com.going.data.dto.request.toTodoCreateRequestDto
+import com.going.domain.entity.request.TodoChangeRequestModel
import com.going.domain.entity.request.TodoCreateRequestModel
import com.going.domain.entity.response.CheckFriendsModel
import com.going.domain.entity.response.MyTripInfoModel
@@ -40,10 +42,11 @@ class TodoRepositoryImpl @Inject constructor(
}
override suspend fun getTodoDetail(
+ tripId: Long,
todoId: Long
): Result =
runCatching {
- todoDataSource.getTodoDetailData(todoId).data.toTodoDetailModel()
+ todoDataSource.getTodoDetailData(tripId, todoId).data.toTodoDetailModel()
}
override suspend fun getMyTripInfo(
@@ -81,4 +84,13 @@ class TodoRepositoryImpl @Inject constructor(
todoDataSource.getFriendsList(tripId).data.toCheckFriendsModel()
}
+ override suspend fun patchTodo(
+ tripId: Long,
+ todoId: Long,
+ request: TodoChangeRequestModel
+ ): Result =
+ runCatching {
+ todoDataSource.patchTodoData(tripId, todoId, request.toTodoChangeRequestDto())
+ }
+
}
\ No newline at end of file
diff --git a/data/src/main/java/com/going/data/service/TodoService.kt b/data/src/main/java/com/going/data/service/TodoService.kt
index e3fdd949..3ec68e8f 100644
--- a/data/src/main/java/com/going/data/service/TodoService.kt
+++ b/data/src/main/java/com/going/data/service/TodoService.kt
@@ -2,6 +2,7 @@ package com.going.data.service
import com.going.data.dto.BaseResponse
import com.going.data.dto.NonDataBaseResponse
+import com.going.data.dto.request.TodoChangeRequestDto
import com.going.data.dto.request.TodoCreateRequestDto
import com.going.data.dto.response.CheckFriendsResponseDto
import com.going.data.dto.response.MyTripInfoResponseDto
@@ -11,6 +12,7 @@ import com.going.data.dto.response.TodoResponseDto
import retrofit2.http.Body
import retrofit2.http.DELETE
import retrofit2.http.GET
+import retrofit2.http.PATCH
import retrofit2.http.POST
import retrofit2.http.Path
import retrofit2.http.Query
@@ -35,8 +37,9 @@ interface TodoService {
@Path("todoId") todoId: Long
): NonDataBaseResponse
- @GET("api/trips/todos/{todoId}")
+ @GET("api/trips/{tripId}/todos/{todoId}")
suspend fun getTodoDetail(
+ @Path("tripId") tripId: Long,
@Path("todoId") todoId: Long
): BaseResponse
@@ -65,4 +68,11 @@ interface TodoService {
@Path("tripId") tripId: Long
): BaseResponse
+ @PATCH("api/trips/{tripId}/todos/{todoId}")
+ suspend fun patchTodo(
+ @Path("tripId") tripId: Long,
+ @Path("todoId") todoId: Long,
+ @Body request: TodoChangeRequestDto
+ ): NonDataBaseResponse
+
}
diff --git a/domain/src/main/kotlin/com/going/domain/entity/request/TodoChangeRequestModel.kt b/domain/src/main/kotlin/com/going/domain/entity/request/TodoChangeRequestModel.kt
new file mode 100644
index 00000000..cd52bfc6
--- /dev/null
+++ b/domain/src/main/kotlin/com/going/domain/entity/request/TodoChangeRequestModel.kt
@@ -0,0 +1,9 @@
+package com.going.domain.entity.request
+
+data class TodoChangeRequestModel(
+ val title: String,
+ val endDate: String,
+ val allocators: List,
+ val memo: String?,
+ val secret: Boolean
+)
\ No newline at end of file
diff --git a/domain/src/main/kotlin/com/going/domain/entity/response/TodoAllocatorModel.kt b/domain/src/main/kotlin/com/going/domain/entity/response/TodoAllocatorModel.kt
index b669ac2e..5c1a0933 100644
--- a/domain/src/main/kotlin/com/going/domain/entity/response/TodoAllocatorModel.kt
+++ b/domain/src/main/kotlin/com/going/domain/entity/response/TodoAllocatorModel.kt
@@ -1,6 +1,8 @@
package com.going.domain.entity.response
data class TodoAllocatorModel(
+ val participantId: Long,
val name: String,
- val isOwner: Boolean
-)
+ val isOwner: Boolean,
+ var isAllocated: Boolean
+)
\ No newline at end of file
diff --git a/domain/src/main/kotlin/com/going/domain/entity/response/TodoListAllocatorModel.kt b/domain/src/main/kotlin/com/going/domain/entity/response/TodoListAllocatorModel.kt
new file mode 100644
index 00000000..6535cfb0
--- /dev/null
+++ b/domain/src/main/kotlin/com/going/domain/entity/response/TodoListAllocatorModel.kt
@@ -0,0 +1,6 @@
+package com.going.domain.entity.response
+
+data class TodoListAllocatorModel(
+ val name: String,
+ val isOwner: Boolean
+)
diff --git a/domain/src/main/kotlin/com/going/domain/entity/response/TodoModel.kt b/domain/src/main/kotlin/com/going/domain/entity/response/TodoModel.kt
index b84bcee6..21be41c7 100644
--- a/domain/src/main/kotlin/com/going/domain/entity/response/TodoModel.kt
+++ b/domain/src/main/kotlin/com/going/domain/entity/response/TodoModel.kt
@@ -4,6 +4,6 @@ data class TodoModel(
val todoId: Long,
val title: String,
val endDate: String,
- val allocators: List,
+ val allocators: List,
val secret: Boolean
)
diff --git a/domain/src/main/kotlin/com/going/domain/repository/TodoRepository.kt b/domain/src/main/kotlin/com/going/domain/repository/TodoRepository.kt
index be7dfbed..080a3a4c 100644
--- a/domain/src/main/kotlin/com/going/domain/repository/TodoRepository.kt
+++ b/domain/src/main/kotlin/com/going/domain/repository/TodoRepository.kt
@@ -1,5 +1,6 @@
package com.going.domain.repository
+import com.going.domain.entity.request.TodoChangeRequestModel
import com.going.domain.entity.request.TodoCreateRequestModel
import com.going.domain.entity.response.CheckFriendsModel
import com.going.domain.entity.response.MyTripInfoModel
@@ -25,6 +26,7 @@ interface TodoRepository {
): Result
suspend fun getTodoDetail(
+ tripId: Long,
todoId: Long
): Result
@@ -47,4 +49,10 @@ interface TodoRepository {
suspend fun getFriendsList(
tripId: Long
): Result
+
+ suspend fun patchTodo(
+ tripId: Long,
+ todoId: Long,
+ request: TodoChangeRequestModel
+ ): Result
}
\ No newline at end of file
diff --git a/presentation/src/main/java/com/going/presentation/todo/allocator/TodoAllocatorAdapter.kt b/presentation/src/main/java/com/going/presentation/todo/allocator/TodoAllocatorAdapter.kt
index 694a0288..befbde4b 100644
--- a/presentation/src/main/java/com/going/presentation/todo/allocator/TodoAllocatorAdapter.kt
+++ b/presentation/src/main/java/com/going/presentation/todo/allocator/TodoAllocatorAdapter.kt
@@ -3,13 +3,13 @@ package com.going.presentation.todo.allocator
import android.view.LayoutInflater
import android.view.ViewGroup
import androidx.recyclerview.widget.ListAdapter
-import com.going.domain.entity.response.TodoAllocatorModel
+import com.going.domain.entity.response.TodoListAllocatorModel
import com.going.presentation.databinding.ItemTodoNameBinding
import com.going.ui.util.ItemDiffCallback
class TodoAllocatorAdapter(
private val isCompleted: Boolean
-) : ListAdapter(diffUtil) {
+) : ListAdapter(diffUtil) {
override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoAllocatorViewHolder {
val inflater by lazy { LayoutInflater.from(parent.context) }
@@ -23,7 +23,7 @@ class TodoAllocatorAdapter(
}
companion object {
- private val diffUtil = ItemDiffCallback(
+ private val diffUtil = ItemDiffCallback(
onItemsTheSame = { old, new -> old.name == new.name },
onContentsTheSame = { old, new -> old == new },
)
diff --git a/presentation/src/main/java/com/going/presentation/todo/allocator/TodoAllocatorViewHolder.kt b/presentation/src/main/java/com/going/presentation/todo/allocator/TodoAllocatorViewHolder.kt
index ebfa3a52..4169aa2d 100644
--- a/presentation/src/main/java/com/going/presentation/todo/allocator/TodoAllocatorViewHolder.kt
+++ b/presentation/src/main/java/com/going/presentation/todo/allocator/TodoAllocatorViewHolder.kt
@@ -1,7 +1,7 @@
package com.going.presentation.todo.allocator
import androidx.recyclerview.widget.RecyclerView
-import com.going.domain.entity.response.TodoAllocatorModel
+import com.going.domain.entity.response.TodoListAllocatorModel
import com.going.presentation.R
import com.going.presentation.databinding.ItemTodoNameBinding
import com.going.ui.extension.colorOf
@@ -11,7 +11,7 @@ class TodoAllocatorViewHolder(
private val isCompleted: Boolean
) : RecyclerView.ViewHolder(binding.root) {
- fun onBind(item: TodoAllocatorModel) {
+ fun onBind(item: TodoListAllocatorModel) {
with(binding.tvTodoName) {
text = item.name
when {
diff --git a/presentation/src/main/java/com/going/presentation/todo/change/TodoAllocatorAdapter.kt b/presentation/src/main/java/com/going/presentation/todo/change/TodoAllocatorAdapter.kt
new file mode 100644
index 00000000..7827f0f5
--- /dev/null
+++ b/presentation/src/main/java/com/going/presentation/todo/change/TodoAllocatorAdapter.kt
@@ -0,0 +1,30 @@
+package com.going.presentation.todo.change
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.ListAdapter
+import com.going.domain.entity.response.TodoAllocatorModel
+import com.going.presentation.databinding.ItemTodoCreateNameBinding
+import com.going.ui.util.ItemDiffCallback
+
+class TodoAllocatorAdapter(
+ private val itemClick: (Int) -> Unit
+) : ListAdapter(diffUtil) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): TodoAllocatorViewHolder {
+ val binding: ItemTodoCreateNameBinding =
+ ItemTodoCreateNameBinding.inflate(LayoutInflater.from(parent.context), parent, false)
+ return TodoAllocatorViewHolder(binding, itemClick)
+ }
+
+ override fun onBindViewHolder(holder: TodoAllocatorViewHolder, position: Int) {
+ holder.onBind(getItem(position), position)
+ }
+
+ companion object {
+ private val diffUtil = ItemDiffCallback(
+ onItemsTheSame = { old, new -> old.participantId == new.participantId },
+ onContentsTheSame = { old, new -> old == new },
+ )
+ }
+}
\ No newline at end of file
diff --git a/presentation/src/main/java/com/going/presentation/todo/change/TodoAllocatorViewHolder.kt b/presentation/src/main/java/com/going/presentation/todo/change/TodoAllocatorViewHolder.kt
new file mode 100644
index 00000000..524c2100
--- /dev/null
+++ b/presentation/src/main/java/com/going/presentation/todo/change/TodoAllocatorViewHolder.kt
@@ -0,0 +1,48 @@
+package com.going.presentation.todo.change
+
+import androidx.recyclerview.widget.RecyclerView
+import com.going.domain.entity.response.TodoAllocatorModel
+import com.going.presentation.R
+import com.going.presentation.databinding.ItemTodoCreateNameBinding
+import com.going.ui.extension.colorOf
+
+class TodoAllocatorViewHolder(
+ val binding: ItemTodoCreateNameBinding,
+ private val itemClick: (Int) -> Unit
+) : RecyclerView.ViewHolder(binding.root) {
+
+ fun onBind(item: TodoAllocatorModel, position: Int) {
+ binding.run {
+ tvTodoName.text = item.name
+ tvTodoName.isSelected = item.isAllocated
+
+ setShapeColor(item.isOwner)
+ setTextColor()
+
+ layoutTodoName.setOnClickListener {
+ itemClick(position)
+ tvTodoName.isSelected = !tvTodoName.isSelected
+ setTextColor()
+ }
+ }
+ }
+
+ private fun setShapeColor(isOwner: Boolean) {
+ with(binding.tvTodoName) {
+ if (isOwner) {
+ setBackgroundResource(R.drawable.sel_todo_shape_red500_fill)
+ } else {
+ setBackgroundResource(R.drawable.sel_todo_shape_gray400_fill)
+ }
+ }
+ }
+ private fun setTextColor() {
+ with(binding.tvTodoName) {
+ if (isSelected) {
+ setTextColor(binding.root.context.colorOf(R.color.white_000))
+ } else {
+ setTextColor(binding.root.context.colorOf(R.color.gray_300))
+ }
+ }
+ }
+}
\ No newline at end of file
diff --git a/presentation/src/main/java/com/going/presentation/todo/change/TodoChangeActivity.kt b/presentation/src/main/java/com/going/presentation/todo/change/TodoChangeActivity.kt
new file mode 100644
index 00000000..644f43f9
--- /dev/null
+++ b/presentation/src/main/java/com/going/presentation/todo/change/TodoChangeActivity.kt
@@ -0,0 +1,184 @@
+package com.going.presentation.todo.change
+
+import android.app.Activity
+import android.content.Context
+import android.content.Intent
+import android.os.Bundle
+import android.view.View
+import androidx.activity.OnBackPressedCallback
+import androidx.activity.viewModels
+import androidx.core.view.isVisible
+import androidx.core.widget.doAfterTextChanged
+import androidx.lifecycle.flowWithLifecycle
+import androidx.lifecycle.lifecycleScope
+import com.going.presentation.R
+import com.going.presentation.databinding.ActivityTodoChangeBinding
+import com.going.presentation.todo.create.TodoCreateActivity.Companion.MAX_MEMO_LEN
+import com.going.presentation.todo.create.TodoCreateActivity.Companion.MAX_TODO_LEN
+import com.going.presentation.todo.detail.TodoDetailActivity
+import com.going.ui.base.BaseActivity
+import com.going.ui.extension.setOnSingleClickListener
+import com.going.ui.extension.toast
+import com.going.ui.state.UiState
+import dagger.hilt.android.AndroidEntryPoint
+import kotlinx.coroutines.flow.launchIn
+import kotlinx.coroutines.flow.onEach
+
+@AndroidEntryPoint
+class TodoChangeActivity : BaseActivity(R.layout.activity_todo_change) {
+
+ private val viewModel by viewModels()
+
+ private var _adapter: TodoAllocatorAdapter? = null
+ private val adapter
+ get() = requireNotNull(_adapter) { getString(R.string.adapter_not_initialized_error_msg) }
+
+ private var todoModDateBottomSheet: TodoModDateBottomSheet? = null
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ initViewModel()
+ initDateClickBtnListener()
+ initFinishBtnListener()
+ initBackBtnListener()
+ getTodoInfo()
+ observeTodoDetailState()
+ observePatchTodoState()
+ setEtTodoNameArguments()
+ setEtTodoMemoArguments()
+ observeNameTextChanged()
+ observeMemoTextChanged()
+ }
+
+ private fun initViewModel() {
+ binding.vm = viewModel
+ }
+
+ private fun initDateClickBtnListener() {
+ binding.etTodoCreateDate.setOnSingleClickListener {
+ todoModDateBottomSheet = TodoModDateBottomSheet()
+ todoModDateBottomSheet?.show(supportFragmentManager, DATE_BOTTOM_SHEET)
+ }
+ }
+
+ private fun initFinishBtnListener() {
+ binding.btnTodoMemoFinish.setOnSingleClickListener {
+ viewModel.patchTodoToServer()
+ }
+ }
+
+ private fun initBackBtnListener() {
+ binding.btnTodoCreateBack.setOnSingleClickListener {
+ finish()
+ }
+ }
+
+ private fun getTodoInfo() {
+ viewModel.tripId = intent.getLongExtra(EXTRA_TRIP_ID, 0)
+ viewModel.todoId = intent.getLongExtra(EXTRA_TODO_ID, 0)
+ viewModel.getTodoDetailFromServer()
+ }
+
+ private fun observeTodoDetailState() {
+ viewModel.todoDetailState.flowWithLifecycle(lifecycle).onEach { state ->
+ when (state) {
+ is UiState.Loading -> return@onEach
+
+ is UiState.Success -> {
+ with(binding) {
+ etTodoCreateTodo.editText.setText(viewModel.todo.value)
+ etTodoCreateMemo.editText.setText(viewModel.memo.value)
+ }
+ if (!state.data.secret) {
+ initOurTodoNameListAdapter()
+ return@onEach
+ }
+ setMyTodoParticipant()
+ }
+
+ is UiState.Failure -> toast(getString(R.string.server_error))
+
+ is UiState.Empty -> return@onEach
+ }
+ }.launchIn(lifecycleScope)
+ }
+
+ private fun observePatchTodoState() {
+ viewModel.todoPatchState.flowWithLifecycle(lifecycle).onEach { result ->
+ if (result) {
+ toast(getString(R.string.todo_change_toast_success))
+ setResult(Activity.RESULT_OK)
+ finish()
+ return@onEach
+ }
+ toast(getString(R.string.todo_change_toast_failure))
+ }.launchIn(lifecycleScope)
+ }
+
+ private fun initOurTodoNameListAdapter() {
+ _adapter = TodoAllocatorAdapter { position ->
+ viewModel.allocatorModelList[position].also { it.isAllocated = !it.isAllocated }
+ viewModel.checkIsFinishAvailable()
+ }
+ binding.rvOurTodoCreatePerson.adapter = adapter
+ adapter.submitList(viewModel.allocatorModelList)
+ binding.etTodoCreateMemo.isVisible = true
+ }
+
+ private fun setMyTodoParticipant() {
+ with(binding) {
+ rvOurTodoCreatePerson.visibility = View.INVISIBLE
+ layoutMyTodoCreatePerson.visibility = View.VISIBLE
+ }
+ }
+
+ private fun setEtTodoNameArguments() {
+ with(binding.etTodoCreateTodo) {
+ setMaxLen(MAX_TODO_LEN)
+ overWarning = getString(R.string.todo_over_error)
+ blankWarning = getString(R.string.name_blank_error)
+ }
+ }
+
+ private fun setEtTodoMemoArguments() {
+ with(binding.etTodoCreateMemo) {
+ setMaxLen(MAX_MEMO_LEN)
+ overWarning = getString(R.string.memo_over_error)
+ }
+ }
+
+ private fun observeNameTextChanged() {
+ binding.etTodoCreateTodo.editText.doAfterTextChanged { text ->
+ viewModel.setNameState(text.toString(), binding.etTodoCreateTodo.state)
+ }
+ }
+
+ private fun observeMemoTextChanged() {
+ binding.etTodoCreateMemo.editText.doAfterTextChanged { text ->
+ viewModel.setMemoState(text.toString(), binding.etTodoCreateMemo.state)
+ }
+ }
+
+ override fun onDestroy() {
+ super.onDestroy()
+ _adapter = null
+ if (todoModDateBottomSheet?.isAdded == true) todoModDateBottomSheet?.dismiss()
+ }
+
+ companion object {
+ private const val DATE_BOTTOM_SHEET = "DATE_BOTTOM_SHEET"
+ private const val EXTRA_TRIP_ID = "EXTRA_TRIP_ID"
+ private const val EXTRA_TODO_ID = "EXTRA_TODO_ID"
+
+ @JvmStatic
+ fun createIntent(
+ context: Context,
+ tripId: Long,
+ todoId: Long
+ ): Intent = Intent(context, TodoChangeActivity::class.java).apply {
+ putExtra(EXTRA_TRIP_ID, tripId)
+ putExtra(EXTRA_TODO_ID, todoId)
+ }
+ }
+}
diff --git a/presentation/src/main/java/com/going/presentation/todo/change/TodoChangeViewModel.kt b/presentation/src/main/java/com/going/presentation/todo/change/TodoChangeViewModel.kt
new file mode 100644
index 00000000..10a9dc2b
--- /dev/null
+++ b/presentation/src/main/java/com/going/presentation/todo/change/TodoChangeViewModel.kt
@@ -0,0 +1,118 @@
+package com.going.presentation.todo.change
+
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.viewModelScope
+import com.going.domain.entity.request.TodoChangeRequestModel
+import com.going.domain.entity.response.TodoAllocatorModel
+import com.going.domain.entity.response.TodoDetailModel
+import com.going.domain.repository.TodoRepository
+import com.going.presentation.designsystem.edittext.EditTextState
+import com.going.ui.state.UiState
+import dagger.hilt.android.lifecycle.HiltViewModel
+import kotlinx.coroutines.flow.MutableSharedFlow
+import kotlinx.coroutines.flow.MutableStateFlow
+import kotlinx.coroutines.flow.SharedFlow
+import kotlinx.coroutines.flow.StateFlow
+import kotlinx.coroutines.launch
+import javax.inject.Inject
+
+@HiltViewModel
+class TodoChangeViewModel @Inject constructor(
+ private val todoRepository: TodoRepository,
+) : ViewModel() {
+
+ private val _todoDetailState = MutableStateFlow>(UiState.Empty)
+ val todoDetailState: StateFlow> = _todoDetailState
+
+ private val _todoPatchState = MutableSharedFlow()
+ val todoPatchState: SharedFlow = _todoPatchState
+
+ val todo = MutableLiveData("")
+ val memo = MutableLiveData("")
+ val endDate = MutableLiveData("")
+
+ private lateinit var oldTodoInfo: TodoDetailModel
+ var isSecret: Boolean = false
+
+ private val isTodoAvailable = MutableLiveData(false)
+ private val isMemoAvailable = MutableLiveData(true)
+ val isFinishAvailable = MutableLiveData(false)
+
+ var allocatorModelList: List = listOf()
+
+ var tripId: Long = 0
+ var todoId: Long = 0
+
+ fun setNameState(name: String, state: EditTextState) {
+ todo.value = name
+ isTodoAvailable.value = state == EditTextState.SUCCESS
+ checkIsFinishAvailable()
+ }
+
+ fun setMemoState(memoText: String, state: EditTextState) {
+ memo.value = memoText
+ isMemoAvailable.value = state != EditTextState.OVER
+ checkIsFinishAvailable()
+ }
+
+ fun checkIsFinishAvailable() {
+ isFinishAvailable.value =
+ (isTodoAvailable.value == true) && (isMemoAvailable.value == true) && (!endDate.value.isNullOrEmpty()) && checkIsTodoChanged()
+ }
+
+ private fun checkIsTodoChanged(): Boolean =
+ (todo.value != oldTodoInfo.title) || (endDate.value != oldTodoInfo.endDate) || (memo.value != oldTodoInfo.memo) || checkIsListChanged()
+
+ private fun checkIsListChanged(): Boolean {
+ for (i in allocatorModelList.indices) {
+ if (oldTodoInfo.allocators[i].isAllocated != allocatorModelList[i].isAllocated) {
+ return true
+ }
+ }
+ return false
+ }
+
+ fun getTodoDetailFromServer() {
+ _todoDetailState.value = UiState.Loading
+ viewModelScope.launch {
+ todoRepository.getTodoDetail(tripId, todoId)
+ .onSuccess { response ->
+ todo.value = response.title
+ endDate.value = response.endDate
+ allocatorModelList = response.allocators.map { it.copy() }
+ memo.value = response.memo
+ isSecret = response.secret
+ oldTodoInfo = response
+ _todoDetailState.value = UiState.Success(response)
+ }
+ .onFailure {
+ _todoDetailState.value = UiState.Failure(it.message.toString())
+ }
+ }
+ }
+
+ fun patchTodoToServer() {
+ if (isFinishAvailable.value == false) return
+ viewModelScope.launch {
+ todoRepository.patchTodo(
+ tripId,
+ todoId,
+ TodoChangeRequestModel(
+ title = todo.value.orEmpty(),
+ endDate = endDate.value.orEmpty(),
+ allocators = allocatorModelList.filter { it.isAllocated }.map { it.participantId },
+ memo = memo.value,
+ secret = isSecret
+ )
+ )
+ .onSuccess {
+ _todoPatchState.emit(true)
+ }
+ .onFailure {
+ _todoPatchState.emit(false)
+ }
+ }
+ }
+
+}
\ No newline at end of file
diff --git a/presentation/src/main/java/com/going/presentation/todo/change/TodoModDateBottomSheet.kt b/presentation/src/main/java/com/going/presentation/todo/change/TodoModDateBottomSheet.kt
new file mode 100644
index 00000000..c611afd3
--- /dev/null
+++ b/presentation/src/main/java/com/going/presentation/todo/change/TodoModDateBottomSheet.kt
@@ -0,0 +1,42 @@
+package com.going.presentation.todo.change
+
+import android.os.Bundle
+import android.view.View
+import androidx.fragment.app.activityViewModels
+import com.going.presentation.R
+import com.going.presentation.databinding.FragmentTodoDateBottomSheetBinding
+import com.going.ui.base.BaseBottomSheet
+import com.going.ui.extension.setOnSingleClickListener
+
+class TodoModDateBottomSheet() :
+ BaseBottomSheet(R.layout.fragment_todo_date_bottom_sheet) {
+
+ private val viewModel by activityViewModels()
+
+ override fun onStart() {
+ super.onStart()
+ dialog?.window?.setBackgroundDrawableResource(R.color.transparent)
+ }
+
+ override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
+ super.onViewCreated(view, savedInstanceState)
+
+ initFinishBtnClickListener()
+ }
+
+ private fun initFinishBtnClickListener() {
+ binding.btnCreateTripFinish.setOnSingleClickListener {
+ val createdMonth = String.format(TWO_DIGIT_FORMAT, binding.dpCreateTripDate.month + 1)
+ val createdDay = String.format(TWO_DIGIT_FORMAT, binding.dpCreateTripDate.dayOfMonth)
+ viewModel.endDate.value =
+ binding.dpCreateTripDate.year.toString() + "." + createdMonth + "." + createdDay
+ viewModel.checkIsFinishAvailable()
+ dismiss()
+ }
+ }
+
+ companion object {
+ const val TWO_DIGIT_FORMAT = "%02d"
+ }
+
+}
\ No newline at end of file
diff --git a/presentation/src/main/java/com/going/presentation/todo/create/TodoCreateActivity.kt b/presentation/src/main/java/com/going/presentation/todo/create/TodoCreateActivity.kt
index b7eb7f4e..a4977be2 100644
--- a/presentation/src/main/java/com/going/presentation/todo/create/TodoCreateActivity.kt
+++ b/presentation/src/main/java/com/going/presentation/todo/create/TodoCreateActivity.kt
@@ -31,15 +31,12 @@ class TodoCreateActivity : BaseActivity(R.layout.acti
private val adapter
get() = requireNotNull(_adapter) { getString(R.string.adapter_not_initialized_error_msg) }
- private var todoDateBottomSheet: TodoDateBottomSheet? = null
-
- private var isOurTodo = true
+ private var todoNewDateBottomSheet: TodoNewDateBottomSheet? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
initViewModel()
- setTodoCreateType()
initDateClickBtnListener()
initFinishBtnListener()
initBackBtnListener()
@@ -59,16 +56,18 @@ class TodoCreateActivity : BaseActivity(R.layout.acti
private fun initDateClickBtnListener() {
binding.etTodoCreateDate.setOnSingleClickListener {
- todoDateBottomSheet = TodoDateBottomSheet()
- todoDateBottomSheet?.show(supportFragmentManager, DATE_BOTTOM_SHEET)
+ todoNewDateBottomSheet = TodoNewDateBottomSheet()
+ todoNewDateBottomSheet?.show(supportFragmentManager, DATE_BOTTOM_SHEET)
}
}
private fun initFinishBtnListener() {
binding.btnTodoMemoFinish.setOnSingleClickListener {
- if (isOurTodo) viewModel.participantIdList =
- adapter.currentList.filter { it.isSelected }.map { it.participantId }
- viewModel.postToCreateTodoFromServer()
+ with(viewModel) {
+ if (isOurTodo) participantIdList =
+ adapter.currentList.filter { it.isSelected }.map { it.participantId }
+ postToCreateTodoFromServer()
+ }
}
}
@@ -81,13 +80,15 @@ class TodoCreateActivity : BaseActivity(R.layout.acti
private fun getTripInfoId() {
with(viewModel) {
tripId = intent.getLongExtra(EXTRA_TRIP_ID, 0)
- participantIdList = intent.getIntegerArrayListExtra(EXTRA_PARTICIPANT_ID)?.map { it.toLong() } ?: listOf()
+ participantIdList =
+ intent.getIntegerArrayListExtra(EXTRA_PARTICIPANT_ID)?.map { it.toLong() }
+ ?: listOf()
}
}
private fun setTodoCreateType() {
- isOurTodo = intent.getBooleanExtra(EXTRA_IS_OUR_TODO, true)
- if (isOurTodo) {
+ viewModel.isOurTodo = intent.getBooleanExtra(EXTRA_IS_OUR_TODO, true)
+ if (viewModel.isOurTodo) {
initOurTodoNameListAdapter()
setOurTodoParticipantList()
} else {
@@ -181,7 +182,7 @@ class TodoCreateActivity : BaseActivity(R.layout.acti
override fun onDestroy() {
super.onDestroy()
_adapter = null
- if (todoDateBottomSheet?.isAdded == true) todoDateBottomSheet?.dismiss()
+ if (todoNewDateBottomSheet?.isAdded == true) todoNewDateBottomSheet?.dismiss()
}
companion object {
@@ -192,8 +193,8 @@ class TodoCreateActivity : BaseActivity(R.layout.acti
private const val EXTRA_NAME = "EXTRA_NAME"
private const val EXTRA_RESULT = "EXTRA_RESULT"
- private const val MAX_TODO_LEN = 15
- private const val MAX_MEMO_LEN = 1000
+ const val MAX_TODO_LEN = 15
+ const val MAX_MEMO_LEN = 1000
@JvmStatic
fun createIntent(
diff --git a/presentation/src/main/java/com/going/presentation/todo/create/TodoCreateViewModel.kt b/presentation/src/main/java/com/going/presentation/todo/create/TodoCreateViewModel.kt
index 6f8c891c..2fe8feec 100644
--- a/presentation/src/main/java/com/going/presentation/todo/create/TodoCreateViewModel.kt
+++ b/presentation/src/main/java/com/going/presentation/todo/create/TodoCreateViewModel.kt
@@ -36,6 +36,8 @@ class TodoCreateViewModel @Inject constructor(
var tripId: Long = 0
+ var isOurTodo = true
+
fun setNameState(name: String, state: EditTextState) {
todo.value = name
isTodoAvailable.value = state == EditTextState.SUCCESS
@@ -50,7 +52,7 @@ class TodoCreateViewModel @Inject constructor(
fun checkIsFinishAvailable() {
isFinishAvailable.value =
- isTodoAvailable.value == true && isMemoAvailable.value == true && !endDate.value.isNullOrEmpty()
+ (isTodoAvailable.value == true) && (isMemoAvailable.value == true) && (!endDate.value.isNullOrEmpty())
}
fun postToCreateTodoFromServer() {
@@ -63,7 +65,7 @@ class TodoCreateViewModel @Inject constructor(
endDate = endDate.value.orEmpty(),
allocators = participantIdList,
memo = memo.value,
- secret = false,
+ secret = !isOurTodo,
),
)
.onSuccess { response ->
diff --git a/presentation/src/main/java/com/going/presentation/todo/create/TodoDateBottomSheet.kt b/presentation/src/main/java/com/going/presentation/todo/create/TodoNewDateBottomSheet.kt
similarity index 97%
rename from presentation/src/main/java/com/going/presentation/todo/create/TodoDateBottomSheet.kt
rename to presentation/src/main/java/com/going/presentation/todo/create/TodoNewDateBottomSheet.kt
index 0743d49a..d56b80f8 100644
--- a/presentation/src/main/java/com/going/presentation/todo/create/TodoDateBottomSheet.kt
+++ b/presentation/src/main/java/com/going/presentation/todo/create/TodoNewDateBottomSheet.kt
@@ -8,7 +8,7 @@ import com.going.presentation.databinding.FragmentTodoDateBottomSheetBinding
import com.going.ui.base.BaseBottomSheet
import com.going.ui.extension.setOnSingleClickListener
-class TodoDateBottomSheet() :
+class TodoNewDateBottomSheet() :
BaseBottomSheet(R.layout.fragment_todo_date_bottom_sheet) {
private val viewModel by activityViewModels()
diff --git a/presentation/src/main/java/com/going/presentation/todo/detail/TodoDetailActivity.kt b/presentation/src/main/java/com/going/presentation/todo/detail/TodoDetailActivity.kt
index 51c7279b..50ed3b6f 100644
--- a/presentation/src/main/java/com/going/presentation/todo/detail/TodoDetailActivity.kt
+++ b/presentation/src/main/java/com/going/presentation/todo/detail/TodoDetailActivity.kt
@@ -1,16 +1,18 @@
package com.going.presentation.todo.detail
+import android.app.Activity
import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.View
+import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.viewModels
import androidx.core.view.isVisible
import androidx.lifecycle.flowWithLifecycle
import androidx.lifecycle.lifecycleScope
import com.going.presentation.R
import com.going.presentation.databinding.ActivityTodoDetailBinding
-import com.going.presentation.todo.create.TodoCreateActivity
+import com.going.presentation.todo.change.TodoChangeActivity
import com.going.ui.base.BaseActivity
import com.going.ui.extension.colorOf
import com.going.ui.extension.drawableOf
@@ -33,9 +35,6 @@ class TodoDetailActivity :
private val adapter
get() = requireNotNull(_adapter) { getString(R.string.adapter_not_initialized_error_msg) }
- private var todoId: Long = 0
- private var isPublic = true
-
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
@@ -43,9 +42,9 @@ class TodoDetailActivity :
initBackBtnClickListener()
initDeleteBtnClickListener()
initModBtnClickListener()
- getTodoId()
- setDetailData()
- setTodoDetailType()
+ getIntentData()
+ initAllocatorListAdapter()
+ resetDetailData()
observeTodoDetailState()
observeTodoDeleteState()
}
@@ -62,34 +61,42 @@ class TodoDetailActivity :
private fun initDeleteBtnClickListener() {
binding.btnTodoDetailDelete.setOnSingleClickListener {
- viewModel.deleteTodoFromServer(todoId)
+ viewModel.deleteTodoFromServer()
}
}
private fun initModBtnClickListener() {
+ val startForResult =
+ registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
+ if (result.resultCode == Activity.RESULT_OK) {
+ finish()
+ }
+ }
binding.btnTodoDetailMod.setOnSingleClickListener {
- toast(getString(R.string.will_be_update))
+ startForResult.launch(
+ TodoChangeActivity.createIntent(
+ this, viewModel.tripId, viewModel.todoId
+ )
+ )
}
}
- private fun getTodoId() {
- todoId = intent.getLongExtra(EXTRA_TODO_ID, 0)
- }
-
- private fun setDetailData() {
- viewModel.getTodoDetailFromServer(todoId)
- }
-
- private fun setTodoDetailType() {
- isPublic = intent.getBooleanExtra(EXTRA_IS_PUBLIC, true)
- if (isPublic) initAllocatorListAdapter()
+ private fun getIntentData() {
+ viewModel.tripId = intent.getLongExtra(EXTRA_TRIP_ID, 0)
+ viewModel.todoId = intent.getLongExtra(EXTRA_TODO_ID, 0)
+ viewModel.isPublic = intent.getBooleanExtra(EXTRA_IS_PUBLIC, true)
}
private fun initAllocatorListAdapter() {
- _adapter = TripAllocatorAdapter()
- binding.rvOurTodoDetailPerson.adapter = adapter
+ if (viewModel.isPublic) {
+ _adapter = TripAllocatorAdapter()
+ binding.rvOurTodoDetailPerson.adapter = adapter
+ }
}
+ private fun resetDetailData() {
+ viewModel.getTodoDetailFromServer()
+ }
private fun observeTodoDetailState() {
viewModel.todoDetailState.flowWithLifecycle(lifecycle).onEach { state ->
@@ -97,7 +104,7 @@ class TodoDetailActivity :
is UiState.Loading -> return@onEach
is UiState.Success -> {
- if (isPublic) {
+ if (viewModel.isPublic) {
adapter.submitList(state.data.allocators)
} else {
with(binding) {
@@ -105,9 +112,17 @@ class TodoDetailActivity :
layoutMyTodoCreatePerson.visibility = View.VISIBLE
}
}
- if (state.data.memo.isBlank()) {
+
+ with(binding) {
+ tvTodoCreateMemoTitle.isVisible = true
+ etTodoCreateMemo.isVisible = true
+ tvTodoMemoCounter.isVisible = true
+ }
+
+ if (state.data.memo.isBlank()) {
with(binding) {
- etTodoCreateMemo.background = drawableOf(R.drawable.shape_rect_4_gray200_line)
+ etTodoCreateMemo.background =
+ drawableOf(R.drawable.shape_rect_4_gray200_line)
etTodoCreateMemo.text = stringOf(R.string.my_todo_create_tv_memo_hint)
etTodoCreateMemo.setTextColor(colorOf(R.color.gray_200))
tvTodoMemoCounter.isVisible = false
@@ -145,15 +160,18 @@ class TodoDetailActivity :
}
companion object {
+ private const val EXTRA_TRIP_ID = "EXTRA_TRIP_ID"
private const val EXTRA_TODO_ID = "EXTRA_TODO_ID"
private const val EXTRA_IS_PUBLIC = "EXTRA_IS_PUBLIC"
@JvmStatic
fun createIntent(
context: Context,
+ tripId: Long,
todoId: Long,
isPublic: Boolean,
): Intent = Intent(context, TodoDetailActivity::class.java).apply {
+ putExtra(EXTRA_TRIP_ID, tripId)
putExtra(EXTRA_TODO_ID, todoId)
putExtra(EXTRA_IS_PUBLIC, isPublic)
}
diff --git a/presentation/src/main/java/com/going/presentation/todo/detail/TodoDetailViewModel.kt b/presentation/src/main/java/com/going/presentation/todo/detail/TodoDetailViewModel.kt
index d9f252ad..8e5b783b 100644
--- a/presentation/src/main/java/com/going/presentation/todo/detail/TodoDetailViewModel.kt
+++ b/presentation/src/main/java/com/going/presentation/todo/detail/TodoDetailViewModel.kt
@@ -3,7 +3,6 @@ package com.going.presentation.todo.detail
import androidx.lifecycle.MutableLiveData
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
-import com.going.domain.entity.response.TodoAllocatorModel
import com.going.domain.entity.response.TodoDetailModel
import com.going.domain.repository.TodoRepository
import com.going.ui.state.EnumUiState
@@ -29,10 +28,14 @@ class TodoDetailViewModel @Inject constructor(
private val _todoDeleteState = MutableStateFlow(EnumUiState.EMPTY)
val todoDeleteState: StateFlow = _todoDeleteState
- fun getTodoDetailFromServer(todoId: Long) {
+ var tripId: Long = 0
+ var todoId: Long = 0
+ var isPublic: Boolean = true
+
+ fun getTodoDetailFromServer() {
_todoDetailState.value = UiState.Loading
viewModelScope.launch {
- todoRepository.getTodoDetail(todoId)
+ todoRepository.getTodoDetail(tripId, todoId)
.onSuccess { response ->
todo.value = response.title
endDate.value = response.endDate
@@ -45,7 +48,7 @@ class TodoDetailViewModel @Inject constructor(
}
}
- fun deleteTodoFromServer(todoId: Long) {
+ fun deleteTodoFromServer() {
_todoDeleteState.value = EnumUiState.LOADING
viewModelScope.launch {
todoRepository.deleteTodo(todoId)
diff --git a/presentation/src/main/java/com/going/presentation/todo/detail/TripAllocatorViewHolder.kt b/presentation/src/main/java/com/going/presentation/todo/detail/TripAllocatorViewHolder.kt
index bd943e5b..20185e00 100644
--- a/presentation/src/main/java/com/going/presentation/todo/detail/TripAllocatorViewHolder.kt
+++ b/presentation/src/main/java/com/going/presentation/todo/detail/TripAllocatorViewHolder.kt
@@ -1,10 +1,10 @@
package com.going.presentation.todo.detail
-import androidx.core.content.ContextCompat
import androidx.recyclerview.widget.RecyclerView
import com.going.domain.entity.response.TodoAllocatorModel
import com.going.presentation.R
import com.going.presentation.databinding.ItemTodoCreateNameBinding
+import com.going.ui.extension.colorOf
class TripAllocatorViewHolder(
val binding: ItemTodoCreateNameBinding
@@ -13,12 +13,15 @@ class TripAllocatorViewHolder(
fun onBind(item: TodoAllocatorModel) {
binding.run {
tvTodoName.text = item.name
- tvTodoName.setTextColor(ContextCompat.getColor(binding.root.context, R.color.white_000))
- if (item.isOwner) {
- tvTodoName.setBackgroundResource(R.drawable.shape_rect_2_red500_fill)
- } else {
- tvTodoName.setBackgroundResource(R.drawable.shape_rect_2_gray400_fill)
+ val (backgroundResource, textColor) = when {
+ !item.isAllocated -> Pair(R.drawable.shape_rect_2_gray300_line, R.color.gray_300)
+ item.isOwner -> Pair(R.drawable.shape_rect_2_red500_fill, R.color.white_000)
+ else -> Pair(R.drawable.shape_rect_2_gray400_fill, R.color.white_000)
+ }
+ tvTodoName.apply {
+ setBackgroundResource(backgroundResource)
+ setTextColor(binding.root.context.colorOf(textColor))
}
}
}
diff --git a/presentation/src/main/java/com/going/presentation/todo/mytodo/todolist/MyTodoCompleteFragment.kt b/presentation/src/main/java/com/going/presentation/todo/mytodo/todolist/MyTodoCompleteFragment.kt
index 9658ef6e..75cf07c4 100644
--- a/presentation/src/main/java/com/going/presentation/todo/mytodo/todolist/MyTodoCompleteFragment.kt
+++ b/presentation/src/main/java/com/going/presentation/todo/mytodo/todolist/MyTodoCompleteFragment.kt
@@ -55,7 +55,7 @@ class MyTodoCompleteFragment() :
},
{ todoModel ->
TodoDetailActivity.createIntent(
- requireContext(), todoModel.todoId, !todoModel.secret
+ requireContext(), viewModel.tripId, todoModel.todoId, !todoModel.secret
).apply { startActivity(this) }
})
binding.rvMyTodoComplete.adapter = adapter
diff --git a/presentation/src/main/java/com/going/presentation/todo/mytodo/todolist/MyTodoUncompleteFragment.kt b/presentation/src/main/java/com/going/presentation/todo/mytodo/todolist/MyTodoUncompleteFragment.kt
index 3f7ed00f..2ab1a438 100644
--- a/presentation/src/main/java/com/going/presentation/todo/mytodo/todolist/MyTodoUncompleteFragment.kt
+++ b/presentation/src/main/java/com/going/presentation/todo/mytodo/todolist/MyTodoUncompleteFragment.kt
@@ -55,7 +55,7 @@ class MyTodoUncompleteFragment() :
{ },
{ todoModel ->
TodoDetailActivity.createIntent(
- requireContext(), todoModel.todoId, !todoModel.secret
+ requireContext(), viewModel.tripId, todoModel.todoId, !todoModel.secret
).apply { startActivity(this) }
})
binding.rvMyTodoUncomplete.adapter = adapter
diff --git a/presentation/src/main/java/com/going/presentation/todo/ourtodo/OurTodoFragment.kt b/presentation/src/main/java/com/going/presentation/todo/ourtodo/OurTodoFragment.kt
index 995f7558..3098e094 100644
--- a/presentation/src/main/java/com/going/presentation/todo/ourtodo/OurTodoFragment.kt
+++ b/presentation/src/main/java/com/going/presentation/todo/ourtodo/OurTodoFragment.kt
@@ -17,19 +17,19 @@ import com.going.domain.entity.response.TripParticipantModel
import com.going.presentation.R
import com.going.presentation.databinding.FragmentOurTodoBinding
import com.going.presentation.todo.TodoActivity.Companion.EXTRA_TRIP_ID
-import com.going.ui.util.RvItemDecoration
-import com.going.presentation.todo.ourtodo.checkfriends.CheckFriendsActivity
import com.going.presentation.todo.create.TodoCreateActivity
+import com.going.presentation.todo.ourtodo.checkfriends.CheckFriendsActivity
import com.going.presentation.todo.ourtodo.friendlist.OurTodoFriendAdapter
import com.going.presentation.todo.ourtodo.invite.FriendInviteDialog
import com.going.presentation.todo.ourtodo.todolist.OurTodoViewPagerAdapter
import com.going.ui.base.BaseFragment
-import com.going.ui.state.UiState
import com.going.ui.extension.colorOf
import com.going.ui.extension.getWindowHeight
import com.going.ui.extension.setOnSingleClickListener
import com.going.ui.extension.setStatusBarColor
import com.going.ui.extension.toast
+import com.going.ui.state.UiState
+import com.going.ui.util.RvItemDecoration
import com.google.android.material.tabs.TabLayout
import com.google.android.material.tabs.TabLayoutMediator
import dagger.hilt.android.AndroidEntryPoint
@@ -59,12 +59,12 @@ class OurTodoFragment() : BaseFragment(R.layout.fragment
super.onViewCreated(view, savedInstanceState)
initAdapter()
+ initTripInfoBtnClickListener()
initAddTodoBtnListener()
initItemDecoration()
initInviteBtnListener()
initBackBtnClickListener()
initTripFriendBtnClickListener()
- initTripInfoBtnClickListener()
setTabLayout()
setViewPager()
setViewPagerChangeListener()
@@ -81,10 +81,20 @@ class OurTodoFragment() : BaseFragment(R.layout.fragment
}
private fun initAdapter() {
- _adapter = OurTodoFriendAdapter()
+ _adapter = OurTodoFriendAdapter(::initFriendInfoListener)
binding.rvOurTripFriend.adapter = adapter
}
+ private fun initFriendInfoListener(participantId: Long) {
+ // TODO: 친구 아이템 클릭 시 상세정보 구현
+ }
+
+ private fun initTripInfoBtnClickListener() {
+ binding.btnOurTodoTripInfo.setOnSingleClickListener {
+ // TODO : 여행정보 화면 이동
+ }
+ }
+
private fun initAddTodoBtnListener() {
binding.btnOurTodoAddTodo.setOnSingleClickListener {
TodoCreateActivity.createIntent(
@@ -129,12 +139,6 @@ class OurTodoFragment() : BaseFragment(R.layout.fragment
}
}
- private fun initTripInfoBtnClickListener() {
- binding.btnOurTodoTripInfo.setOnSingleClickListener {
- // TODO : 여행정보 화면 이동
- }
- }
-
private fun setOurTripInfo() {
arguments?.let {
viewModel.tripId = it.getLong(EXTRA_TRIP_ID)
@@ -200,9 +204,10 @@ class OurTodoFragment() : BaseFragment(R.layout.fragment
val displayHeight = activity?.getWindowHeight() ?: return@addOnOffsetChangedListener
val toolbarHeight = binding.toolbarOurTodo.height
val appBarHeight = appBarLayout.totalScrollRange + verticalOffset
- binding.layoutOurTodoEmpty.layoutParams = (binding.layoutOurTodoEmpty.layoutParams).also {
- it.height = displayHeight - toolbarHeight - appBarHeight - 300
- }
+ binding.layoutOurTodoEmpty.layoutParams =
+ (binding.layoutOurTodoEmpty.layoutParams).also {
+ it.height = displayHeight - toolbarHeight - appBarHeight - 300
+ }
if (abs(verticalOffset) == appBarLayout.totalScrollRange) {
setStatusBarColor(R.color.white_000)
@@ -252,7 +257,8 @@ class OurTodoFragment() : BaseFragment(R.layout.fragment
private fun setTitleTextWithDay(day: Int, isComplete: Boolean) {
when {
day > 0 -> {
- binding.tvOurTodoTitleDown.text = getString(R.string.our_todo_title_down_before).format(day)
+ binding.tvOurTodoTitleDown.text =
+ getString(R.string.our_todo_title_down_before).format(day)
setDateTextColor(6, 6)
}
diff --git a/presentation/src/main/java/com/going/presentation/todo/ourtodo/friendlist/OurTodoFriendAdapter.kt b/presentation/src/main/java/com/going/presentation/todo/ourtodo/friendlist/OurTodoFriendAdapter.kt
index bc697dc5..cdd68805 100644
--- a/presentation/src/main/java/com/going/presentation/todo/ourtodo/friendlist/OurTodoFriendAdapter.kt
+++ b/presentation/src/main/java/com/going/presentation/todo/ourtodo/friendlist/OurTodoFriendAdapter.kt
@@ -6,7 +6,9 @@ import androidx.recyclerview.widget.RecyclerView
import com.going.domain.entity.response.TripParticipantModel
import com.going.presentation.databinding.ItemTodoFriendsBinding
-class OurTodoFriendAdapter : RecyclerView.Adapter() {
+class OurTodoFriendAdapter(
+ private val onClicked: (Long) -> (Unit)
+) : RecyclerView.Adapter() {
private var itemList = mutableListOf()
@@ -14,7 +16,7 @@ class OurTodoFriendAdapter : RecyclerView.Adapter() {
val inflater by lazy { LayoutInflater.from(parent.context) }
val binding: ItemTodoFriendsBinding =
ItemTodoFriendsBinding.inflate(inflater, parent, false)
- return OurTodoFriendViewHolder(binding)
+ return OurTodoFriendViewHolder(binding, onClicked)
}
override fun onBindViewHolder(holder: OurTodoFriendViewHolder, position: Int) {
diff --git a/presentation/src/main/java/com/going/presentation/todo/ourtodo/friendlist/OurTodoFriendViewHolder.kt b/presentation/src/main/java/com/going/presentation/todo/ourtodo/friendlist/OurTodoFriendViewHolder.kt
index cf829bbe..a2e60fb6 100644
--- a/presentation/src/main/java/com/going/presentation/todo/ourtodo/friendlist/OurTodoFriendViewHolder.kt
+++ b/presentation/src/main/java/com/going/presentation/todo/ourtodo/friendlist/OurTodoFriendViewHolder.kt
@@ -6,8 +6,12 @@ import coil.transform.CircleCropTransformation
import com.going.domain.entity.response.TripParticipantModel
import com.going.presentation.R
import com.going.presentation.databinding.ItemTodoFriendsBinding
+import com.going.ui.extension.setOnSingleClickListener
-class OurTodoFriendViewHolder(val binding: ItemTodoFriendsBinding) :
+class OurTodoFriendViewHolder(
+ val binding: ItemTodoFriendsBinding,
+ private val onClicked: (Long) -> (Unit)
+) :
RecyclerView.ViewHolder(binding.root) {
fun onBind(item: TripParticipantModel) {
@@ -24,10 +28,15 @@ class OurTodoFriendViewHolder(val binding: ItemTodoFriendsBinding) :
6 -> R.drawable.img_profile_7
else -> R.drawable.img_profile_3
}
+
ivTodoFriend.load(profileImage) {
transformations(CircleCropTransformation())
}
+ root.setOnSingleClickListener {
+ onClicked(item.participantId)
+ }
+
}
}
diff --git a/presentation/src/main/java/com/going/presentation/todo/ourtodo/todolist/OurTodoCompleteFragment.kt b/presentation/src/main/java/com/going/presentation/todo/ourtodo/todolist/OurTodoCompleteFragment.kt
index dd0104eb..9a223414 100644
--- a/presentation/src/main/java/com/going/presentation/todo/ourtodo/todolist/OurTodoCompleteFragment.kt
+++ b/presentation/src/main/java/com/going/presentation/todo/ourtodo/todolist/OurTodoCompleteFragment.kt
@@ -50,7 +50,7 @@ class OurTodoCompleteFragment() :
true
) { todoId ->
TodoDetailActivity.createIntent(
- requireContext(), todoId, true
+ requireContext(), viewModel.tripId, todoId, true
).apply { startActivity(this) }
}
binding.rvOurTodoComplete.adapter = adapter
diff --git a/presentation/src/main/java/com/going/presentation/todo/ourtodo/todolist/OurTodoUncompleteFragment.kt b/presentation/src/main/java/com/going/presentation/todo/ourtodo/todolist/OurTodoUncompleteFragment.kt
index dc0b5d83..035464a1 100644
--- a/presentation/src/main/java/com/going/presentation/todo/ourtodo/todolist/OurTodoUncompleteFragment.kt
+++ b/presentation/src/main/java/com/going/presentation/todo/ourtodo/todolist/OurTodoUncompleteFragment.kt
@@ -50,7 +50,7 @@ class OurTodoUncompleteFragment() :
false
) { todoId ->
TodoDetailActivity.createIntent(
- requireContext(), todoId, true
+ requireContext(), viewModel.tripId, todoId, true
).apply { startActivity(this) }
}
binding.rvOurTodoUncomplete.adapter = adapter
diff --git a/presentation/src/main/res/layout/activity_todo_change.xml b/presentation/src/main/res/layout/activity_todo_change.xml
new file mode 100644
index 00000000..14ec84a8
--- /dev/null
+++ b/presentation/src/main/res/layout/activity_todo_change.xml
@@ -0,0 +1,254 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/presentation/src/main/res/layout/activity_todo_detail.xml b/presentation/src/main/res/layout/activity_todo_detail.xml
index 7a5931ff..1eddbbad 100644
--- a/presentation/src/main/res/layout/activity_todo_detail.xml
+++ b/presentation/src/main/res/layout/activity_todo_detail.xml
@@ -91,8 +91,9 @@
android:layout_marginHorizontal="24dp"
android:layout_marginTop="6dp"
android:background="@drawable/shape_rect_4_gray700_line"
- android:paddingHorizontal="12dp"
- android:paddingVertical="19dp"
+ android:paddingVertical="20dp"
+ android:paddingStart="16dp"
+ android:paddingEnd="30dp"
android:text="@={vm.todo}"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
@@ -105,6 +106,7 @@
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_marginTop="4dp"
+ android:layout_marginEnd="4dp"
android:text="@{@string/counter(vm.todo.length, vm.MAX_TODO_LEN)}"
android:textColor="@color/gray_400"
app:layout_constraintEnd_toEndOf="@id/et_todo_detail_todo"
@@ -239,9 +241,11 @@
android:layout_marginHorizontal="24dp"
android:layout_marginTop="40dp"
android:text="@string/my_todo_create_tv_memo"
+ android:visibility="gone"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
- app:layout_constraintTop_toBottomOf="@id/rv_our_todo_detail_person" />
+ app:layout_constraintTop_toBottomOf="@id/rv_our_todo_detail_person"
+ tools:visibility="visible" />
+ tools:text="오늘 완전 완전 맛있는 파스타를 먹었는데 완전 아주 그냥 이게 말이지"
+ tools:visibility="visible" />
+ tools:text="0/1000"
+ tools:visibility="visible" />
diff --git a/presentation/src/main/res/layout/view_emoji_counter_edittext.xml b/presentation/src/main/res/layout/view_emoji_counter_edittext.xml
index f92ab255..7156f150 100644
--- a/presentation/src/main/res/layout/view_emoji_counter_edittext.xml
+++ b/presentation/src/main/res/layout/view_emoji_counter_edittext.xml
@@ -21,11 +21,12 @@
android:layout_height="wrap_content"
android:layout_marginTop="6dp"
android:background="@drawable/shape_rect_4_gray200_line"
- android:paddingEnd="30dp"
android:gravity="top"
android:includeFontPadding="false"
android:inputType="textMultiLine"
+ android:lineSpacingMultiplier="1.2"
android:paddingVertical="20dp"
+ android:paddingEnd="30dp"
android:textAppearance="@style/TextAppearance.Doorip.Body3.Medi"
android:textColorHint="@color/gray_200"
app:layout_constraintEnd_toEndOf="parent"
@@ -34,11 +35,11 @@
@@ -64,5 +65,4 @@
app:layout_constraintEnd_toEndOf="@id/et_emoji_counter_et_content"
app:layout_constraintTop_toBottomOf="@id/et_emoji_counter_et_content" />
-
diff --git a/presentation/src/main/res/values/strings.xml b/presentation/src/main/res/values/strings.xml
index 84342a44..08c6a002 100644
--- a/presentation/src/main/res/values/strings.xml
+++ b/presentation/src/main/res/values/strings.xml
@@ -112,6 +112,11 @@
수정하기
할일을 삭제했어요
+
+ 할일 수정
+ 할일을 수정했어요
+ 할일 수정에 실패했어요
+
초대하기
초대코드를 보내 여행 친구를 추가해 보세요
@@ -237,5 +242,4 @@
취소
여행 이름에는 공백만 입력할 수 없어요
-