Skip to content

Commit

Permalink
홈 화면 캘린더 연도 전환 구현 (#41)
Browse files Browse the repository at this point in the history
* 🔨 홈 화면 학사일정 API year 추가

* 🔨 홈 화면 학사일정 연도 기능 추가

* 🔨 SuppressLint 추가
  • Loading branch information
GyeongminKimGyeongminKim authored Sep 30, 2024
1 parent 688dfa3 commit 474f16a
Show file tree
Hide file tree
Showing 9 changed files with 73 additions and 33 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ interface UnivDataSource {
suspend fun getDeptContact(): Response<BaseResponse<List<DeptContactResDTO>>>

suspend fun getMonthlyAcademicSchedule(
year: Int,
month: Int,
ssaId: String
): Response<BaseResponse<List<AcademicScheduleResDTO>>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,10 +22,11 @@ class UnivDataSourceImpl @Inject constructor(
}

override suspend fun getMonthlyAcademicSchedule(
year: Int,
month: Int,
ssaId: String
): Response<BaseResponse<List<AcademicScheduleResDTO>>> {
return service.getMonthlyAcademicSchedule(month = month, ssaId = ssaId)
return service.getMonthlyAcademicSchedule(year= year, month = month, ssaId = ssaId)
}

override suspend fun getBanner(): Response<BaseResponse<List<BannerResDTO>>> {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ interface UnivService {

@GET("/api/academic-schedule/monthly")
suspend fun getMonthlyAcademicSchedule(
@Query("year") year: Int,
@Query("month") month: Int,
@Query("ssaid") ssaId: String
): Response<BaseResponse<List<AcademicScheduleResDTO>>>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,10 +33,10 @@ class UnivRepositoryImpl @Inject constructor(
)
}

override suspend fun getMonthlyAcademicSchedule(month: Int, ssaId: String): Result<List<AcademicSchedule>> {
override suspend fun getMonthlyAcademicSchedule(year: Int, month: Int, ssaId: String): Result<List<AcademicSchedule>> {
return handleResponse(
dataNullSafe = false,
call = { datasource.getMonthlyAcademicSchedule(month, ssaId) },
call = { datasource.getMonthlyAcademicSchedule(year, month, ssaId) },
onSuccess = { data ->
data?.map { AcademicSchedule(id = it.id, title = it.title, marked = it.marked, startDate = it.startDate, endDate = it.endDate) } ?: emptyList()
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ interface UnivRepository {

suspend fun getDeptContact(): Result<List<DeptContact>>

suspend fun getMonthlyAcademicSchedule(month: Int, ssaId: String): Result<List<AcademicSchedule>>
suspend fun getMonthlyAcademicSchedule(year: Int, month: Int, ssaId: String): Result<List<AcademicSchedule>>

suspend fun getBanner(): Result<List<Banner>>
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ class GetAcademicScheduleUseCase @Inject constructor(
private val repository: UnivRepository
) {

suspend operator fun invoke(month: Int, ssaId: String): Result<List<AcademicSchedule>> {
return repository.getMonthlyAcademicSchedule(month, ssaId)
suspend operator fun invoke(year: Int, month: Int, ssaId: String): Result<List<AcademicSchedule>> {
return repository.getMonthlyAcademicSchedule(year, month, ssaId)
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.neverland.thinkerbell.view.home

import android.view.View
import androidx.fragment.app.viewModels
import androidx.recyclerview.widget.LinearLayoutManager
import androidx.recyclerview.widget.PagerSnapHelper
Expand All @@ -20,9 +21,11 @@ class HomeCalendarFragment : BaseFragment<FragmentHomeCalendarBinding>() {
private val viewModel: HomeCalendarViewModel by viewModels()
private lateinit var monthAdapter: CalendarMonthAdapter
private lateinit var scheduleAdapter: CalendarScheduleAdapter
private var currentYear = Calendar.getInstance().get(Calendar.YEAR) // 현재 연도를 저장
private var currentMonth = Calendar.getInstance().get(Calendar.MONTH) + 1 // 현재 월을 저장 (1월이 1)

override fun initView() {
fetchSchedulesForCurrentMonth()
fetchSchedulesForCurrentMonth() // 초기 데이터를 불러오기 위해 현재 연도와 월로 데이터 요청
setCalendarRv()
setScheduleRv()
}
Expand All @@ -34,14 +37,20 @@ class HomeCalendarFragment : BaseFragment<FragmentHomeCalendarBinding>() {
when (state) {
is UiState.Loading -> {
// Handle loading state if necessary
binding.rvSchedule.visibility = View.VISIBLE
}
is UiState.Success -> {
// 성공 상태에서만 업데이트 수행
monthAdapter.setData(state.data)
updateSchedules(state.data)
binding.rvSchedule.visibility = View.VISIBLE
}
is UiState.Error -> {
// Handle error state if necessary
if (state.exception.message?.contains("현재 년도의 +-1의 년도 사이만 입력가능합니다.") == true) {
// 에러 메시지가 해당 조건에 맞으면 리사이클러뷰를 GONE 처리
binding.rvSchedule.visibility = View.GONE
}
}
UiState.Empty -> {
// Handle empty state if necessary
Expand All @@ -51,28 +60,24 @@ class HomeCalendarFragment : BaseFragment<FragmentHomeCalendarBinding>() {

viewModel.toastState.observe(viewLifecycleOwner) { state ->
when (state) {
is UiState.Loading -> {}
is UiState.Error -> {}
is UiState.Empty -> {}
is UiState.Success -> {
showToast(state.data)
}
else -> {}
}
}
}

private fun fetchSchedulesForCurrentMonth() {
val calendar = Calendar.getInstance()
val currentMonth = calendar.get(Calendar.MONTH) + 1
viewModel.fetchData(currentMonth)
viewModel.fetchData(currentYear, currentMonth) // 연도와 월을 같이 사용해 데이터 요청
}

private fun setScheduleRv() {
binding.rvSchedule.layoutManager = LinearLayoutManager(context)
scheduleAdapter = CalendarScheduleAdapter().apply {
setRvItemClickListener(object : OnRvItemClickListener<Pair<Int, Boolean>> {
override fun onClick(item: Pair<Int, Boolean>) {
if(item.second) viewModel.postBookmark(item.first) else viewModel.deleteBookmark(item.first)
if (item.second) viewModel.postBookmark(item.first) else viewModel.deleteBookmark(item.first)
}
})
}
Expand All @@ -89,9 +94,14 @@ class HomeCalendarFragment : BaseFragment<FragmentHomeCalendarBinding>() {
binding.rvCalendar.scrollToPosition(newPosition)
val calendar = monthAdapter.baseCalendar.clone() as Calendar
calendar.add(Calendar.MONTH, newPosition - Int.MAX_VALUE / 2)
val month = calendar.get(Calendar.MONTH) + 1
viewModel.fetchData(month)

val newMonth = calendar.get(Calendar.MONTH) + 1
currentYear = calendar.get(Calendar.YEAR) // 새로운 연도 설정
currentMonth = newMonth // 새로운 월 설정

viewModel.fetchData(currentYear, currentMonth) // 연도와 월에 맞게 데이터를 갱신
}

binding.rvCalendar.layoutManager = object : LinearLayoutManager(context, HORIZONTAL, false) {
override fun canScrollHorizontally(): Boolean = false
}
Expand Down Expand Up @@ -124,11 +134,19 @@ class HomeCalendarFragment : BaseFragment<FragmentHomeCalendarBinding>() {
private fun updateSchedule(position: Int) {
val calendar = Calendar.getInstance()
calendar.add(Calendar.MONTH, position - Int.MAX_VALUE / 2)
val month = calendar.get(Calendar.MONTH) + 1

val newMonth = calendar.get(Calendar.MONTH) + 1
currentYear = calendar.get(Calendar.YEAR) // 현재 연도 업데이트
currentMonth = newMonth // 현재 월 업데이트

val filteredSchedules = when (val state = viewModel.uiState.value) {
is UiState.Success -> state.data.filter { it.startDate.startsWith(String.format("%02d", month)) }
else -> emptyList() // 성공 상태가 아니면 빈 리스트 반환
is UiState.Success -> state.data.filter { schedule ->
// 스케줄의 시작 날짜와 현재 연도, 월이 같은지 확인
val scheduleYear = schedule.startDate.substring(0, 4).toInt()
val scheduleMonth = schedule.startDate.substring(5, 7).toInt()
scheduleYear == currentYear && scheduleMonth == currentMonth
}
else -> emptyList()
}
scheduleAdapter.updateSchedules(filteredSchedules)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,15 +23,16 @@ class HomeCalendarViewModel @Inject constructor(
private val deleteBookmarkUseCase: DeleteBookmarkUseCase
): ViewModel() {


private val _uiState = MutableLiveData<UiState<List<AcademicSchedule>>>(UiState.Loading)
val uiState: LiveData<UiState<List<AcademicSchedule>>> get() = _uiState

fun fetchData(month: Int) {
// 연도와 월을 기반으로 데이터를 가져오는 함수로 수정
fun fetchData(year: Int, month: Int) {
_uiState.value = UiState.Loading

viewModelScope.launch {
getAcademicScheduleUseCase.invoke(month, ssaId = application.getAndroidId())
// UseCase에 연도와 월을 함께 전달하도록 수정
getAcademicScheduleUseCase.invoke(year, month, ssaId = application.getAndroidId())
.onSuccess { schedules ->
_uiState.value = UiState.Success(schedules)
}
Expand All @@ -44,7 +45,7 @@ class HomeCalendarViewModel @Inject constructor(
private val _toastState = MutableLiveData<UiState<String>>(UiState.Loading)
val toastState: LiveData<UiState<String>> get() = _toastState

fun postBookmark(noticeId: Int){
fun postBookmark(noticeId: Int) {
val category = NoticeType.ACADEMIC_SCHEDULE

viewModelScope.launch {
Expand All @@ -61,11 +62,10 @@ class HomeCalendarViewModel @Inject constructor(
LoggerUtil.d("[${category.koName}] 즐겨찾기 성공")
_toastState.value = UiState.Success("즐겨찾기 되었습니다")
}

}
}

fun deleteBookmark(noticeId: Int){
fun deleteBookmark(noticeId: Int) {
val category = NoticeType.ACADEMIC_SCHEDULE

viewModelScope.launch {
Expand All @@ -84,4 +84,4 @@ class HomeCalendarViewModel @Inject constructor(
}
}
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.neverland.thinkerbell.view.home.adapter

import android.annotation.SuppressLint
import android.view.LayoutInflater
import android.view.View
import android.view.ViewGroup
Expand All @@ -16,13 +17,17 @@ class CalendarMonthAdapter(
private var scheduleList: List<AcademicSchedule>,
private val onMonthChange: (Int) -> Unit
) : RecyclerView.Adapter<CalendarMonthAdapter.Month>() {

val baseCalendar: Calendar = Calendar.getInstance()
private var currentYear = baseCalendar.get(Calendar.YEAR) // 현재 연도를 저장
private var currentMonth = baseCalendar.get(Calendar.MONTH) // 현재 월을 저장

override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): Month {
val view = LayoutInflater.from(parent.context).inflate(R.layout.item_calendar_month, parent, false)
return Month(view)
}

@SuppressLint("SetTextI18n")
override fun onBindViewHolder(holder: Month, position: Int) {
// 리사이클러뷰 초기화
val listLayout: RecyclerView = holder.view.findViewById(R.id.rv_month)
Expand All @@ -32,11 +37,13 @@ class CalendarMonthAdapter(
calendar.set(Calendar.DAY_OF_MONTH, 1)
calendar.add(Calendar.MONTH, position - Int.MAX_VALUE / 2) // 정확한 월 계산

// title 텍스트 초기화
val titleText: TextView = holder.view.findViewById(R.id.tv_month)
titleText.text = "${calendar.get(Calendar.MONTH) + 1}"
// 연도와 월 설정
val month = calendar.get(Calendar.MONTH) // 월 (0부터 시작)
val year = calendar.get(Calendar.YEAR) // 연도

val tempMonth = calendar.get(Calendar.MONTH)
// title 텍스트 초기화 (연도 + 월 표시)
val titleText: TextView = holder.view.findViewById(R.id.tv_month)
titleText.text = "${year}${month + 1}"

// 일 구하기
val dayList: MutableList<Date> = MutableList(6 * 7) { Date() }
Expand All @@ -49,18 +56,29 @@ class CalendarMonthAdapter(
}

listLayout.layoutManager = GridLayoutManager(holder.view.context, 7)
listLayout.adapter = CalendarDayAdapter(tempMonth, dayList, scheduleList)
listLayout.adapter = CalendarDayAdapter(month, dayList, scheduleList)

// 화살표 버튼 클릭 이벤트 처리
val btnPrevMonth: ImageButton = holder.view.findViewById(R.id.btn_prev_month)
val btnNextMonth: ImageButton = holder.view.findViewById(R.id.btn_next_month)

btnPrevMonth.setOnClickListener {
if (position > 0) {
onMonthChange(position - 1)
if (currentMonth == 0) {
currentMonth = 11 // 1월에서 이전으로 가면 12월로 이동
currentYear-- // 연도를 이전 연도로 변경
} else {
currentMonth--
}
onMonthChange(position - 1)
}

btnNextMonth.setOnClickListener {
if (currentMonth == 11) {
currentMonth = 0 // 12월에서 다음으로 가면 1월로 이동
currentYear++ // 연도를 다음 연도로 변경
} else {
currentMonth++
}
onMonthChange(position + 1)
}
}
Expand All @@ -69,6 +87,7 @@ class CalendarMonthAdapter(
return Int.MAX_VALUE
}

@SuppressLint("NotifyDataSetChanged")
fun setData(newList: List<AcademicSchedule>) {
scheduleList = newList
notifyDataSetChanged()
Expand Down

0 comments on commit 474f16a

Please sign in to comment.