diff --git a/app/src/main/java/umc/com/mobile/project/ui/board/GradDateFragment.kt b/app/src/main/java/umc/com/mobile/project/ui/board/GradDateFragment.kt index c42e9c3..a64d122 100644 --- a/app/src/main/java/umc/com/mobile/project/ui/board/GradDateFragment.kt +++ b/app/src/main/java/umc/com/mobile/project/ui/board/GradDateFragment.kt @@ -9,6 +9,7 @@ import android.view.LayoutInflater import android.view.View import android.view.ViewGroup import android.widget.Toast +import androidx.core.content.ContextCompat import androidx.fragment.app.DialogFragment import androidx.fragment.app.activityViewModels import androidx.lifecycle.Observer @@ -24,128 +25,139 @@ import java.time.format.DateTimeFormatter import java.util.Locale class GradDateFragment : Fragment() { - private var _binding: FragmentGradDateBinding? = null - private lateinit var mContext: Context - private var bottomSheetBinding: FragmentGradDateBottomBinding? = null - private val viewModel: GradDateViewModel by activityViewModels() - private val binding get() = _binding!! - - override fun onCreateView( - inflater: LayoutInflater, - container: ViewGroup?, - savedInstanceState: Bundle? - ): View { - _binding = FragmentGradDateBinding.inflate(inflater, container, false) - binding.vm = viewModel - mContext = requireContext() - bottomSheetBinding = - FragmentGradDateBottomBinding.inflate(layoutInflater) // bottomSheetBinding 초기화 - - with(binding) { - tvGradDateDate.setOnClickListener { - val bottomSheet = GradDateBottomFragment(mContext) - bottomSheet.setStyle( - DialogFragment.STYLE_NORMAL, - umc.com.mobile.project.R.style.RoundCornerBottomSheetDialogTheme - ) - bottomSheet.show(requireActivity().supportFragmentManager, bottomSheet.tag) - } - } - - navigateBack() // 뒤로 가기 버튼 클릭 시 - initTodayDate() // 오늘 날짜 설정 - - viewModel.dateResponse.observe(viewLifecycleOwner, Observer { response -> - if (response != null && response.result != null) { - binding.tvGradDateDday.text = "D-" + response.result.dday.toString() - } - }) - - binding.btnSave.setOnClickListener { - val originalFormat = SimpleDateFormat("yyyy-M월-d", Locale.KOREA) - val targetFormat = SimpleDateFormat("yyyy-MM-dd", Locale.KOREA) - - val dateString = viewModel.selectedDateRequest.value - if (dateString != null) { - try { - val date = originalFormat.parse(dateString) - val formattedDate = targetFormat.format(date) - viewModel.updateCheeringMessage(binding.tvGradDateMemo.text.toString()) - viewModel.updateDateInfo(formattedDate) - Toast.makeText(context, "저장되었습니다.", Toast.LENGTH_LONG).show() - navigate(R.id.action_fragment_date_to_fragment_home) - viewModel.onEditButtonClick() - } catch (e: ParseException) { - Log.e("GradDateFragment", "Error parsing date", e) - Toast.makeText(context, "날짜를 올바른 형식으로 입력해주세요.", Toast.LENGTH_LONG).show() - } - } else { - Toast.makeText(context, "졸업예정일을 선택해주세요.", Toast.LENGTH_LONG).show() - } - } - - return binding.root - } - - override fun onViewCreated(view: View, savedInstanceState: Bundle?) { - super.onViewCreated(view, savedInstanceState) - - viewModel.getDateInfo() - - viewModel._selectedDate.observe(viewLifecycleOwner) { date -> - binding.tvGradDateDate.text = date - } - - viewModel._dday.observe(viewLifecycleOwner) { dday -> - binding.tvGradDateDday.text = "D-$dday" - } - - viewModel.dateResponse.observe(viewLifecycleOwner, Observer { response -> - if (response != null && response.result != null) { - val inputFormat = SimpleDateFormat("yyyy-MM-dd", Locale.KOREA) - val outputFormat = SimpleDateFormat("졸업 예정일 yyyy'년' MM'월' dd'일'", Locale.KOREA) - - val dateStr = inputFormat.parse(response.result.gradDate) - if (dateStr != null) { - val formattedDateStr = outputFormat.format(dateStr) - binding.tvGradDateDate.text = formattedDateStr - } - - binding.tvGradDateDday.text = "D-" + response.result.dday.toString() - } - }) - - viewModel.cheeringMessage.observe(viewLifecycleOwner) { message -> - binding.tvGradDateMemo.text = Editable.Factory.getInstance().newEditable(message) - } - - viewModel.isEditMode.observe(viewLifecycleOwner, Observer { isEditMode -> - if (isEditMode) { - binding.tvGradDateEdit.visibility = View.GONE - binding.btnSave.visibility = View.VISIBLE - } else { - binding.tvGradDateEdit.visibility = View.VISIBLE - binding.btnSave.visibility = View.GONE - } - }) - } - - override fun onDestroyView() { - super.onDestroyView() - _binding = null - } - - private fun navigateBack() { - binding.btnBack.setOnClickListener { - navigate(R.id.action_fragment_date_to_fragment_home) - } - } - - private fun initTodayDate() { - val currentTime = LocalDateTime.now() - val pattern = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일") - - binding.tvGradDateToday.text = currentTime.format(pattern) - } + private var _binding: FragmentGradDateBinding? = null + private lateinit var mContext: Context + private var bottomSheetBinding: FragmentGradDateBottomBinding? = null + private val viewModel: GradDateViewModel by activityViewModels() + private val binding get() = _binding!! + + override fun onCreateView( + inflater: LayoutInflater, + container: ViewGroup?, + savedInstanceState: Bundle? + ): View { + _binding = FragmentGradDateBinding.inflate(inflater, container, false) + binding.vm = viewModel + mContext = requireContext() + bottomSheetBinding = + FragmentGradDateBottomBinding.inflate(layoutInflater) // bottomSheetBinding 초기화 + + with(binding) { + tvGradDateDate.setOnClickListener { + val bottomSheet = GradDateBottomFragment(mContext) + bottomSheet.setStyle( + DialogFragment.STYLE_NORMAL, + umc.com.mobile.project.R.style.RoundCornerBottomSheetDialogTheme + ) + bottomSheet.show(requireActivity().supportFragmentManager, bottomSheet.tag) + } + } + + navigateBack() // 뒤로 가기 버튼 클릭 시 + initTodayDate() // 오늘 날짜 설정 + + binding.btnSave.setOnClickListener { + val originalFormat = SimpleDateFormat("yyyy-M월-d", Locale.KOREA) + val targetFormat = SimpleDateFormat("yyyy-MM-dd", Locale.KOREA) + + val dateString = viewModel.selectedDateRequest.value + if (dateString != null) { + try { + val date = originalFormat.parse(dateString) + val formattedDate = targetFormat.format(date) + viewModel.updateDateInfo(formattedDate) + Toast.makeText(context, "저장되었습니다.", Toast.LENGTH_LONG).show() + navigate(R.id.action_fragment_date_to_fragment_home) + viewModel.onEditButtonClick() + } catch (e: ParseException) { + Log.e("GradDateFragment", "Error parsing date", e) + Toast.makeText(context, "날짜를 올바른 형식으로 입력해주세요.", Toast.LENGTH_LONG).show() + } + } else { + Toast.makeText(context, "졸업예정일을 선택해주세요.", Toast.LENGTH_LONG).show() + } + } + + return binding.root + } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + super.onViewCreated(view, savedInstanceState) + + viewModel.getDateInfo() + + //전에 저장했던 졸업일자랑 dday 불러오기 + viewModel.dateResponse.observe(viewLifecycleOwner, Observer { response -> + if (response != null && response.result != null) { + val inputFormat = SimpleDateFormat("yyyy-MM-dd", Locale.KOREA) + val outputFormat = SimpleDateFormat("졸업 예정일 yyyy'년' MM'월' dd'일'", Locale.KOREA) + + val dateStr = inputFormat.parse(response.result.gradDate) + if (dateStr != null) { + val formattedDateStr = outputFormat.format(dateStr) + binding.tvGradDateDate.text = formattedDateStr + } + binding.tvGradDateDday.text = "D-" + response.result.dday.toString() + } + }) + //다시 선택한 졸업 일자 띄우기 + viewModel._selectedDate.observe(viewLifecycleOwner) { date -> + binding.tvGradDateDate.text = date + } + //다시 선택한 졸업 일자에 맞춰 dday 띄우기 + viewModel._dday.observe(viewLifecycleOwner) { dday -> + binding.tvGradDateDday.text = "D-$dday" + } + + //수정하기 및 버튼 visible 조건 + viewModel.isEditMode.observe(viewLifecycleOwner, Observer { isEditMode -> + if (isEditMode) { + binding.tvGradDateEdit.visibility = View.GONE + binding.btnSave.visibility = View.VISIBLE + binding.tvGradDateDate.isEnabled = true + binding.tvGradDateMemo.isEnabled = true + } else { + binding.tvGradDateEdit.visibility = View.VISIBLE + binding.btnSave.visibility = View.GONE + binding.tvGradDateDate.isEnabled = false + binding.tvGradDateMemo.isEnabled = false + } + }) + //버튼 활성화 조건 + viewModel.isButtonEnabled.observe(viewLifecycleOwner, Observer { isEnabled -> + if (isEnabled) { + binding.btnSave.apply { + this.isEnabled = true + this.backgroundTintList = + ContextCompat.getColorStateList(context, R.color.white) + this.setTextColor(ContextCompat.getColor(context, R.color.skyBlue)) + } + } else { + binding.btnSave.apply { + this.isEnabled = false + this.backgroundTintList = ContextCompat.getColorStateList(context, R.color.gray) + this.setTextColor(ContextCompat.getColor(context, R.color.white)) + } + } + }) + } + + override fun onDestroyView() { + super.onDestroyView() + _binding = null + } + + private fun navigateBack() { + binding.btnBack.setOnClickListener { + navigate(R.id.action_fragment_date_to_fragment_home) + } + } + + private fun initTodayDate() { + val currentTime = LocalDateTime.now() + val pattern = DateTimeFormatter.ofPattern("yyyy년 MM월 dd일") + + binding.tvGradDateToday.text = currentTime.format(pattern) + } } \ No newline at end of file diff --git a/app/src/main/java/umc/com/mobile/project/ui/board/viewmodel/GradDateViewModel.kt b/app/src/main/java/umc/com/mobile/project/ui/board/viewmodel/GradDateViewModel.kt index b69a2c7..42f68ff 100644 --- a/app/src/main/java/umc/com/mobile/project/ui/board/viewmodel/GradDateViewModel.kt +++ b/app/src/main/java/umc/com/mobile/project/ui/board/viewmodel/GradDateViewModel.kt @@ -1,6 +1,6 @@ package umc.com.mobile.project.ui.board.viewmodel + import android.util.Log -import androidx.databinding.ObservableBoolean import androidx.lifecycle.LiveData import androidx.lifecycle.MediatorLiveData import androidx.lifecycle.MutableLiveData @@ -17,145 +17,157 @@ import java.time.LocalDate import java.time.format.DateTimeFormatter import java.time.temporal.ChronoUnit - class GradDateViewModel : ViewModel() { - val _selectedDate: MutableLiveData = MutableLiveData() - val selectedDate: LiveData - get() = _selectedDate - - val _selectedDateRequest: MutableLiveData = MutableLiveData() - val selectedDateRequest: LiveData - get() = _selectedDateRequest - - private val dateInfoApiService = ApiClient.createService() - - private val _dateResponse: MutableLiveData = MutableLiveData() - val dateResponse: MutableLiveData - get() = _dateResponse - - private val _updateDateResponse: MutableLiveData = MutableLiveData() - val updateDateResponse: MutableLiveData - get() = _updateDateResponse - - private val _error: MutableLiveData = MutableLiveData() - val error: LiveData - get() = _error - - val _dday: MutableLiveData = MutableLiveData() - val dday: LiveData - get() = _dday - - private val _cheeringMessage: MutableLiveData = MutableLiveData() - val cheeringMessage: LiveData - get() = _cheeringMessage - - private val _isEditMode = MutableLiveData(false) - val isEditMode: LiveData - get() = _isEditMode - - fun init(value: GradDateResponse) { - _dday.postValue(value.result.dday) - _cheeringMessage.postValue(value.result.message) - } - - val isFilledMemo: LiveData = MediatorLiveData().apply { - addSource(cheeringMessage) { value = isFieldFilled() } - } - fun isFieldFilled(): Boolean { - return !cheeringMessage.value.isNullOrEmpty() - } - - fun updateSelectedDate(year: String, month: String, day: String) { - val selectedDateString = "졸업 예정일 ${year}년 $month ${day}일" - _selectedDate.value = selectedDateString - _selectedDateRequest.value = "${year}-${month}-${day}" - calculateDDay(year, month, day) - } - - fun calculateDDay(year: String, month: String, day: String) { - val monthNumber = month.replace("월", "").trim().padStart(2, '0') - val dayNumber = day.padStart(2, '0') - - val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") - val selectedDate = LocalDate.parse("$year-$monthNumber-$dayNumber", formatter) - val currentDate = LocalDate.now() - - _dday.value = ChronoUnit.DAYS.between(currentDate, selectedDate).toInt() - } - - fun updateCheeringMessage(message: String) { - _cheeringMessage.value = message - } - - fun onEditButtonClick() { - _isEditMode.value = !_isEditMode.value!! - } - - fun getDateInfo() { - dateInfoApiService.getDateInfo().enqueue(object : Callback { - override fun onResponse( - call: Call, - response: Response - ) { - if (response.isSuccessful) { - val dateInfoResponse = response.body() - if (dateInfoResponse != null) { - dateResponse.postValue(dateInfoResponse) - if (dateResponse.value != null && dateResponse.value!!.result != null) { - _selectedDate.value = dateResponse.value!!.result.gradDate - } - Log.d("gradDate", "${response.body()}") - } else { - _error.postValue("서버 응답이 올바르지 않습니다.") - } - } else { - _error.postValue("사용자 정보를 가져오지 못했습니다.") - try { - throw response.errorBody()?.string()?.let { - RuntimeException(it) - } ?: RuntimeException("Unknown error") - } catch (e: Exception) { - Log.e("gradDate", "API 오류: ${e.message}") - } - } - } - override fun onFailure(call: Call, t: Throwable) { - _error.postValue("네트워크 오류: ${t.message}") - Log.d("gradDate", "${t.message}") - } - }) - } - fun updateDateInfo(date: String) { - dateInfoApiService.updateDateInfo( - UpdateGradDateRequest(date, cheeringMessage.value.orEmpty()) - ).enqueue(object : Callback { - override fun onResponse( - call: Call, - response: Response - ) { - if (response.isSuccessful) { - val updateDateInfoResponse = response.body() - if (updateDateInfoResponse != null) { - updateDateResponse.postValue(updateDateInfoResponse) - Log.d("updateGradDate", "${response.body()}") - } else { - _error.postValue("서버 응답이 올바르지 않습니다.") - } - } else { - _error.postValue("사용자 정보를 가져오지 못했습니다.") - try { - throw response.errorBody()?.string()?.let { - RuntimeException(it) - } ?: RuntimeException("Unknown error") - } catch (e: Exception) { - Log.e("updateGradDate", "API 오류: ${e.message}") - } - } - } - override fun onFailure(call: Call, t: Throwable) { - _error.postValue("네트워크 오류: ${t.message}") - Log.d("updateGradDate", "${t.message}") - } - }) - } + val _selectedDate: MutableLiveData = MutableLiveData() + val selectedDate: LiveData + get() = _selectedDate + + val _selectedDateRequest: MutableLiveData = MutableLiveData() + val selectedDateRequest: LiveData + get() = _selectedDateRequest + + private val dateInfoApiService = ApiClient.createService() + + //졸업예정일에서는 안 씀-> home에 코드 있어서 놔둠 + private val _dateResponse: MutableLiveData = MutableLiveData() + val dateResponse: MutableLiveData + get() = _dateResponse + + //졸업예정일이 쓰는 response + val _dateResponse2: MutableLiveData = MutableLiveData() + + private val _updateDateResponse: MutableLiveData = MutableLiveData() + val updateDateResponse: MutableLiveData + get() = _updateDateResponse + + private val _error: MutableLiveData = MutableLiveData() + val error: LiveData + get() = _error + + val _dday: MutableLiveData = MutableLiveData() + val dday: LiveData + get() = _dday + + val cheeringMessage: MutableLiveData = MutableLiveData() + + private val _isEditMode = MutableLiveData(false) + val isEditMode: LiveData + get() = _isEditMode + + init { + cheeringMessage.value = "" + } + + fun updateSelectedDate(year: String, month: String, day: String) { + val selectedDateString = "졸업 예정일 ${year}년 $month ${day}일" + _selectedDate.value = selectedDateString + _selectedDateRequest.value = "${year}-${month}-${day}" + calculateDDay(year, month, day) + } + + fun calculateDDay(year: String, month: String, day: String) { + val monthNumber = month.replace("월", "").trim().padStart(2, '0') + val dayNumber = day.padStart(2, '0') + + val formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd") + val selectedDate = LocalDate.parse("$year-$monthNumber-$dayNumber", formatter) + val currentDate = LocalDate.now() + + _dday.value = ChronoUnit.DAYS.between(currentDate, selectedDate).toInt() + } + + //버튼 말고 수정하기 text + fun onEditButtonClick() { + _isEditMode.value = !_isEditMode.value!! + } + + //전의 메모랑 같으면 저장 안됨 + private var previousMessage: String? = null + private var previousDDay: Int? = null + + val isButtonEnabled = MediatorLiveData().apply { + //cheeringMessage 값이 변경될 때마다 실행 + addSource(cheeringMessage) { currentMessage -> + value = previousMessage != currentMessage + previousMessage = currentMessage + } + //_dday 값이 변경될 때마다 실행 + addSource(_dday) { currentDDay -> + value = previousDDay != currentDDay + previousDDay = currentDDay + } + } + + fun getDateInfo() { + dateInfoApiService.getDateInfo().enqueue(object : Callback { + override fun onResponse( + call: Call, + response: Response + ) { + if (response.isSuccessful) { + val dateInfoResponse = response.body() + if (dateInfoResponse != null) { + dateResponse.postValue(dateInfoResponse)//home에 있어서 놔둠 + _dateResponse2.postValue(dateInfoResponse) + if (_dateResponse2.value != null && _dateResponse2.value!!.result != null) { + _selectedDate.value = _dateResponse2.value!!.result.gradDate + Log.d("getSelectedDate", selectedDate.value.toString()) + } + Log.d("gradDate", "${response.body()}") + } else { + _error.postValue("서버 응답이 올바르지 않습니다.") + } + } else { + _error.postValue("사용자 정보를 가져오지 못했습니다.") + try { + throw response.errorBody()?.string()?.let { + RuntimeException(it) + } ?: RuntimeException("Unknown error") + } catch (e: Exception) { + Log.e("gradDate", "API 오류: ${e.message}") + } + } + } + + override fun onFailure(call: Call, t: Throwable) { + _error.postValue("네트워크 오류: ${t.message}") + Log.d("gradDate", "${t.message}") + } + }) + } + + fun updateDateInfo(date: String) { + dateInfoApiService.updateDateInfo( + UpdateGradDateRequest(date, cheeringMessage.value.orEmpty()) + ).enqueue(object : Callback { + override fun onResponse( + call: Call, + response: Response + ) { + if (response.isSuccessful) { + val updateDateInfoResponse = response.body() + if (updateDateInfoResponse != null) { + updateDateResponse.postValue(updateDateInfoResponse) + Log.d("updateGradDate", "${response.body()}") + } else { + _error.postValue("서버 응답이 올바르지 않습니다.") + } + } else { + _error.postValue("사용자 정보를 가져오지 못했습니다.") + try { + throw response.errorBody()?.string()?.let { + RuntimeException(it) + } ?: RuntimeException("Unknown error") + } catch (e: Exception) { + Log.e("updateGradDate", "API 오류: ${e.message}") + } + } + } + + override fun onFailure(call: Call, t: Throwable) { + _error.postValue("네트워크 오류: ${t.message}") + Log.d("updateGradDate", "${t.message}") + } + }) + } } \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_grad_date.xml b/app/src/main/res/layout/fragment_grad_date.xml index c178b0e..517ab29 100644 --- a/app/src/main/res/layout/fragment_grad_date.xml +++ b/app/src/main/res/layout/fragment_grad_date.xml @@ -131,10 +131,10 @@ android:background="@drawable/bg_solid_white_radius_10" android:gravity="top" android:hint="@string/board_grad_date_memo" - android:inputType="text" android:paddingStart="12dp" android:paddingTop="17dp" android:paddingBottom="106dp" + android:text="@={vm.cheeringMessage}" android:textColorHint="#B3B3B3" app:layout_constraintBottom_toTopOf="@+id/btn_save" app:layout_constraintEnd_toEndOf="@+id/iv_grad_date_card2" @@ -163,7 +163,7 @@ android:layout_height="wrap_content" android:layout_marginBottom="6dp" android:background="@drawable/bg_solid_gray_radius_25" - android:backgroundTint="@color/white" + android:backgroundTint="@color/gray" android:minHeight="0dp" android:paddingTop="17dp" android:paddingBottom="17dp"