Skip to content

Commit

Permalink
Merge pull request #140 from woowacourse-teams/AN/feature/120-studyma…
Browse files Browse the repository at this point in the history
…nagement-inflate

[스터디 관리하기 뷰 시작 후] 스터디 관리하기 뷰 기능 구현
  • Loading branch information
RightHennessy authored Aug 2, 2023
2 parents 619f282 + c9a9439 commit f695277
Show file tree
Hide file tree
Showing 51 changed files with 1,020 additions and 76 deletions.
3 changes: 2 additions & 1 deletion android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,8 @@
tools:targetApi="31">
<activity
android:name=".presentation.studyManagement.StudyManagementActivity"
android:exported="false" />
android:exported="false"
android:windowSoftInputMode="adjustPan" />
<activity
android:name=".presentation.splash.SplashActivity"
android:exported="false" />
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,5 +7,5 @@ interface HomeDataSource {

suspend fun getUserStudies(): UserStudiesResponseDto

suspend fun patchTodo(studyId: Int, todoId: Int, todoRequestDto: TodoRequestDto)
suspend fun patchTodo(studyId: Int, todoId: Long, todoRequestDto: TodoRequestDto)
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ class HomeDataSourceImpl(
return homeService.getUserStudies()
}

override suspend fun patchTodo(studyId: Int, todoId: Int, todoRequestDto: TodoRequestDto) {
override suspend fun patchTodo(studyId: Int, todoId: Long, todoRequestDto: TodoRequestDto) {
homeService.patchTodo(
studyId = studyId,
todoId = todoId,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ interface HomeService {
@PATCH("/v1/studies/{studyId}/todos/{todoId}")
suspend fun patchTodo(
@Path("studyId") studyId: Int,
@Path("todoId") todoId: Int,
@Path("todoId") todoId: Long,
@Body todoRequestDto: TodoRequestDto,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ data class TodoResponseDto(
@SerialName("content")
val content: String,
@SerialName("id")
val id: Int,
val id: Long,
@SerialName("isDone")
val isDone: Boolean,
)
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.created.team201.presentation.common

interface TodoClickListener {

fun clickOnTodo(id: Long, isDone: Boolean)
}
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ class SinglePicker @JvmOverloads constructor(
getInteger(R.styleable.SinglePicker_minValue, DEFAULT_VALUE)
binding.npSinglePicker.maxValue =
getInteger(R.styleable.SinglePicker_maxValue, DEFAULT_VALUE)
binding.tvSinglePicker.text = getString(R.styleable.SinglePicker_title)
binding.tvSinglePicker.text = getString(R.styleable.SinglePicker_singlePickerTitle)
}.also {
recycle()
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
package com.created.team201.presentation.home

interface HomeClickListener {
import com.created.team201.presentation.common.TodoClickListener

fun clickOnTodo(id: Int, isDone: Boolean)
interface HomeClickListener : TodoClickListener {

override fun clickOnTodo(id: Long, isDone: Boolean)

fun clickOnStudyCard(studyId: Long)
}
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ class HomeFragment : BindingFragment<FragmentHomeBinding>(R.layout.fragment_home
}

private fun implementClickListener() = object : HomeClickListener {
override fun clickOnTodo(id: Int, isDone: Boolean) {
override fun clickOnTodo(id: Long, isDone: Boolean) {
homeViewModel.updateTodo(id, !isDone)
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ class HomeViewModel(
}
}

fun updateTodo(todoId: Int, isDone: Boolean) {
fun updateTodo(todoId: Long, isDone: Boolean) {
val studies = userStudies.value ?: throw IllegalArgumentException()
val isNecessary = studies.any { it.necessaryTodo.todoId == todoId }
val study: StudyUiModel
Expand Down Expand Up @@ -83,15 +83,15 @@ class HomeViewModel(
}
}

private fun updateNecessaryTodoCheck(studies: List<StudyUiModel>, id: Int, isDone: Boolean) {
private fun updateNecessaryTodoCheck(studies: List<StudyUiModel>, id: Long, isDone: Boolean) {
_userStudies.value = studies.map { studyUiModel ->
studyUiModel.takeIf { it.necessaryTodo.todoId != id } ?: studyUiModel.copy(
necessaryTodo = studyUiModel.necessaryTodo.copy(isDone = isDone),
)
}
}

private fun updateOptionalTodoCheck(studies: List<StudyUiModel>, id: Int, isDone: Boolean) {
private fun updateOptionalTodoCheck(studies: List<StudyUiModel>, id: Long, isDone: Boolean) {
_userStudies.value = studies.map { studyUiModel ->
studyUiModel.takeIf { todoUiModel -> !todoUiModel.optionalTodos.any { it.todoId == id } }
?: studyUiModel.copy(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
package com.created.team201.presentation.home.model

data class TodoUiModel(
val todoId: Int,
val todoId: Long,
val content: String,
val isDone: Boolean,
)
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.created.team201.presentation.studyManage.adapter

import android.util.Log
import android.view.LayoutInflater
import android.view.ViewGroup
import android.widget.LinearLayout.VERTICAL
Expand Down Expand Up @@ -42,7 +41,6 @@ class StudyManageViewHolder(
}

fun bind(item: MyStudiesUiModel) {
Log.d("hello", item.studySummariesUiModel.toString())
studyListAdapter.submitList(item.studySummariesUiModel)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
package com.created.team201.presentation.studyManagement

import com.created.domain.model.Role
import com.created.domain.model.Round
import com.created.team201.presentation.home.model.TodoUiModel
import com.created.team201.presentation.studyManagement.model.OptionalTodoUiModel
import com.created.team201.presentation.studyManagement.model.StudyMemberUiModel
import com.created.team201.presentation.studyManagement.model.StudyRoundDetailUiModel

val dummy: List<StudyRoundDetailUiModel> = listOf(
StudyRoundDetailUiModel(
1L,
11L,
Role.MASTER,
TodoUiModel(1L, "책읽기 모두", true),
listOf(
OptionalTodoUiModel(TodoUiModel(2L, "블로그 정리", false), 0),
OptionalTodoUiModel(TodoUiModel(3L, "블로그 정리22", false), 0),
),
listOf(
StudyMemberUiModel(1L, true, "반달", "", true),
StudyMemberUiModel(2L, false, "산군", "", false),
StudyMemberUiModel(3L, false, "써니", "", true),
StudyMemberUiModel(4L, false, "링링", "", true),
),
),
StudyRoundDetailUiModel(
2L,
11L,
Role.MASTER,
TodoUiModel(1L, "책읽기 모두", true),
listOf(
OptionalTodoUiModel(TodoUiModel(2L, "블로그 정리", false), 0),
OptionalTodoUiModel(TodoUiModel(3L, "블로그 정리22", false), 0),
),
listOf(
StudyMemberUiModel(1L, true, "반달", "", true),
StudyMemberUiModel(2L, false, "산군", "", true),
StudyMemberUiModel(3L, false, "써니", "", true),
StudyMemberUiModel(4L, false, "링링", "", true),
),
),
StudyRoundDetailUiModel(
3L,
11L,
Role.MASTER,
TodoUiModel(1L, "책읽기 모두", true),
listOf(
OptionalTodoUiModel(TodoUiModel(2L, "블로그 정리", false), 0),
OptionalTodoUiModel(TodoUiModel(3L, "블로그 정리22", false), 0),
),
listOf(
StudyMemberUiModel(1L, true, "반달", "", true),
StudyMemberUiModel(2L, false, "산군", "", true),
StudyMemberUiModel(3L, false, "써니", "", true),
StudyMemberUiModel(4L, false, "링링", "", true),
),
),
)

val roundDummy = listOf(
Round(1L, 1),
Round(2L, 2),
Round(3L, 3),
)
Original file line number Diff line number Diff line change
@@ -1,29 +1,159 @@
package com.created.team201.presentation.studyManagement

import android.content.Context
import android.content.Intent
import android.os.Bundle
import android.view.MenuItem
import android.widget.Toast
import androidx.activity.viewModels
import androidx.viewpager2.widget.ViewPager2
import com.created.domain.model.PageIndex
import com.created.team201.R
import com.created.team201.databinding.ActivityStudyManagementBinding
import com.created.team201.presentation.common.BindingActivity
import com.created.team201.presentation.studyManagement.adapter.StudyManagementAdapter

class StudyManagementActivity :
BindingActivity<ActivityStudyManagementBinding>(R.layout.activity_study_management) {

private val studyManagementViewModel by viewModels<StudyManagementViewModel>()
private val studyManagementAdapter: StudyManagementAdapter by lazy {
StudyManagementAdapter(studyManagementClickListener, memberClickListener)
}

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)

initViewModel()
initActionBar()
initStudyInformation()
initStudyRounds()
initAdapter()
initPageButtonClickListener()
observeStudyManagement()
}

private fun initViewModel() {
binding.viewModel = studyManagementViewModel
binding.lifecycleOwner = this
}

private fun initActionBar() {
setSupportActionBar(binding.tbStudyManagement)
supportActionBar?.setDisplayShowTitleEnabled(false)
supportActionBar?.setDisplayHomeAsUpEnabled(true)
supportActionBar?.setHomeAsUpIndicator(R.drawable.ic_back)
}

private fun initStudyInformation() {
studyManagementViewModel.fetchStudyInformation()
}

private fun initStudyRounds() {
val studyId = intent.getLongExtra(KEY_STUDY_ID, KEY_ERROR)
val roundId = intent.getLongExtra(KEY_ROUND_ID, KEY_ERROR)
studyManagementViewModel.getStudyRounds(studyId, roundId)
}

private fun initAdapter() {
binding.vpStudyManagement.adapter = studyManagementAdapter
}

private fun observeStudyManagement() {
studyManagementViewModel.studyRounds.observe(this) { studyRoundDetails ->
studyManagementAdapter.submitList(studyRoundDetails)
}
binding.vpStudyManagement.registerOnPageChangeCallback(
object : ViewPager2.OnPageChangeCallback() {
override fun onPageSelected(position: Int) {
super.onPageSelected(position)

studyManagementViewModel.updateCurrentPage(PageIndex(position))
setPageChangeButtonEnabled()
}
},
)
}

private fun setPageChangeButtonEnabled() {
binding.ivStudyManagementPreviousButton.isEnabled =
studyManagementViewModel.currentRound.value != FIRST_ROUND
binding.ivStudyManagementNextButton.isEnabled =
studyManagementViewModel.currentRound.value != studyManagementViewModel.studyInformation.totalRoundCount
}

private val studyManagementClickListener = object : StudyManagementClickListener {
override fun clickOnTodo(id: Long, isDone: Boolean) {
val currentItemId = binding.vpStudyManagement.currentItem
studyManagementViewModel.updateTodo(currentItemId, id, !isDone)
}

override fun onClickAddTodo(todoContent: String) {
if (todoContent.isEmpty()) {
toastEmptyTodoInput()
return
}
val currentPage = binding.vpStudyManagement.currentItem
val studyId = intent.getLongExtra(KEY_STUDY_ID, KEY_ERROR)
studyManagementViewModel.addOptionalTodo(studyId, currentPage, todoContent)
}

override fun onClickAddOptionalTodo(optionalTodoCount: Int) {
if (optionalTodoCount >= MAXIMUM_OPTIONAL_TODO_COUNT) {
Toast.makeText(
this@StudyManagementActivity,
getString(R.string.study_management_not_allowed_add_optional_todo),
Toast.LENGTH_SHORT,
).show()
}
}
}

private fun toastEmptyTodoInput() {
Toast.makeText(
this@StudyManagementActivity,
getString(R.string.study_management_not_allowed_empty_content),
Toast.LENGTH_SHORT,
).show()
}

private val memberClickListener = object : StudyMemberClickListener {
override fun onClickMember(id: Long) {
// 프로필 페이지로 이동
}
}

private fun initPageButtonClickListener() {
binding.ivStudyManagementPreviousButton.setOnClickListener {
val page = PageIndex(binding.vpStudyManagement.currentItem).decrease()
binding.vpStudyManagement.setCurrentItem(page.number, true)
studyManagementViewModel.fetchRoundDetail(page)
}
binding.ivStudyManagementNextButton.setOnClickListener {
val page =
PageIndex(binding.vpStudyManagement.currentItem).increase(studyManagementAdapter.itemCount - 1)
binding.vpStudyManagement.setCurrentItem(page.number, true)
studyManagementViewModel.fetchRoundDetail(page)
}
}

override fun onOptionsItemSelected(item: MenuItem): Boolean {
if (item.itemId == android.R.id.home) {
finish()
}
return super.onOptionsItemSelected(item)
}

companion object {
private const val FIRST_ROUND = 1
private const val MAXIMUM_OPTIONAL_TODO_COUNT = 4
private const val KEY_ERROR = 0L
private const val KEY_STUDY_ID = "KEY_STUDY_ID"
private const val KEY_ROUND_ID = "KEY_ROUND_ID"
fun getIntent(context: Context, studyId: Long, roundId: Long): Intent =
Intent(context, StudyManagementActivity::class.java).apply {
putExtra(KEY_STUDY_ID, studyId)
putExtra(KEY_ROUND_ID, roundId)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package com.created.team201.presentation.studyManagement

import com.created.team201.presentation.common.TodoClickListener

interface StudyManagementClickListener : TodoClickListener {

override fun clickOnTodo(id: Long, isDone: Boolean)

fun onClickAddTodo(todoContent: String)

fun onClickAddOptionalTodo(optionalTodoCount: Int)
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.created.team201.presentation.studyManagement

import androidx.annotation.StringRes
import com.created.team201.R

sealed class StudyManagementState(
@StringRes
val title: Int,
@StringRes
val buttonText: Int,
) {
object Master : StudyManagementState(
R.string.study_management_app_bar_title_is_study_master,
R.string.study_management_end_button_is_study_master,
)

object Member : StudyManagementState(
R.string.study_management_app_bar_title_is_study_participant,
R.string.study_management_end_button_is_study_participant,
)
}
Loading

0 comments on commit f695277

Please sign in to comment.