diff --git a/app/src/main/java/com/example/shiftalarm/CalendarAdapter.kt b/app/src/main/java/com/example/shiftalarm/CalendarAdapter.kt index 984504a..0f9d900 100644 --- a/app/src/main/java/com/example/shiftalarm/CalendarAdapter.kt +++ b/app/src/main/java/com/example/shiftalarm/CalendarAdapter.kt @@ -13,18 +13,18 @@ import androidx.recyclerview.widget.RecyclerView import java.time.LocalDate data class DayShift( - val date: LocalDate?, - val shift: String?, - val hasMemo: Boolean = false, - val memoContent: String? = null + val date: LocalDate?, + val shift: String?, + val hasMemo: Boolean = false, + val memoContent: String? = null ) class CalendarAdapter( - var days: List, - private val listener: OnDayClickListener, - var showHolidays: Boolean = true + var days: List, + private val listener: OnDayClickListener, + var showHolidays: Boolean = true, + private val rowCount: Int = 6 // Default to 6 rows ) : RecyclerView.Adapter() { - interface OnDayClickListener { fun onDayClick(date: LocalDate, currentShift: String) } @@ -48,18 +48,32 @@ class CalendarAdapter( return (dp * context.resources.displayMetrics.density).toInt() } - override fun onBindViewHolder(holder: ViewHolder, position: Int) { - val item = days[position] - val context = holder.itemView.context - - if (item.date == null) { - holder.itemView.visibility = View.INVISIBLE - return - } - - holder.itemView.visibility = View.VISIBLE - - // Day Number + override fun onBindViewHolder(holder: ViewHolder, position: Int) { + val item = days[position] + val context = holder.itemView.context + + // Dynamically adjust item height based on row count (5 or 6 rows) + val displayMetrics = context.resources.displayMetrics + val screenWidth = displayMetrics.widthPixels + val itemWidth = screenWidth / 7 // Each cell width + val itemHeight = if (rowCount == 5) { + (itemWidth * 1.2).toInt() // Taller items for 5 rows to fill space + } else { + itemWidth // Square items for 6 rows + } + + val layoutParams = holder.itemView.layoutParams + layoutParams.height = itemHeight + holder.itemView.layoutParams = layoutParams + + if (item.date == null) { + holder.itemView.visibility = View.INVISIBLE + return + } + + holder.itemView.visibility = View.VISIBLE + + // Day Number holder.dayNumber.text = item.date.dayOfMonth.toString() // Holiday / Weekend logic diff --git a/app/src/main/java/com/example/shiftalarm/MainActivity.kt b/app/src/main/java/com/example/shiftalarm/MainActivity.kt index d8f4240..599067a 100644 --- a/app/src/main/java/com/example/shiftalarm/MainActivity.kt +++ b/app/src/main/java/com/example/shiftalarm/MainActivity.kt @@ -187,22 +187,33 @@ class MainActivity : AppCompatActivity() { } } - override fun onResume() { - super.onResume() - val prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) - currentViewTeam = prefs.getString(KEY_TEAM, "A") ?: "A" - - updateTideButtonVisibility() - updateCalendar() - - // 일원화된 통합 권한 체크 실행 (신뢰도 100% 보장) - AlarmPermissionUtil.checkAndRequestAllPermissions(this) + override fun onResume() { + super.onResume() + val prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) + currentViewTeam = prefs.getString(KEY_TEAM, "A") ?: "A" - // 설정 변경 시 즉시 반영을 위한 강제 동기화 (30일 스케줄링) - lifecycleScope.launch { - syncAllAlarms(this@MainActivity) - } - } + updateTideButtonVisibility() + updateCalendar() + + // 일원화된 통합 권한 체크 실행 (신뢰도 100% 보장) + AlarmPermissionUtil.checkAndRequestAllPermissions(this) + + // 설정 변경 시 즉시 반영을 위한 강제 동기화 (30일 스케줄링) + lifecycleScope.launch { + syncAllAlarms(this@MainActivity) + } + + // 연차 정보 업데이트 + lifecycleScope.launch { + val repo = ShiftRepository(this@MainActivity) + val annualLeave = repo.getAnnualLeave() + annualLeave?.let { + binding.tvAnnualLeave.text = "연차: ${String.format("%.1f", it.remainingDays)}" + } ?: run { + binding.tvAnnualLeave.text = "연차: --" + } + } + } private fun showMonthYearPicker() { val dialogView = layoutInflater.inflate(R.layout.dialog_month_year_picker, null) @@ -255,10 +266,11 @@ class MainActivity : AppCompatActivity() { return (dp * resources.displayMetrics.density).toInt() } - private fun setupCalendar() { - binding.calendarGrid.layoutManager = GridLayoutManager(this, 7) - updateCalendar() - } + private fun setupCalendar() { + binding.calendarGrid.layoutManager = GridLayoutManager(this, 7) + binding.calendarGrid.setHasFixedSize(false) // Allow dynamic item sizing + updateCalendar() + } private fun updateCalendar() { val prefs = getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE) @@ -294,14 +306,20 @@ class MainActivity : AppCompatActivity() { dao.getMemosForMonth(monthStr).associateBy { memoItem -> memoItem.date } } - val days = generateDaysForMonthWithData(currentViewMonth, currentViewTeam, factory, overrides, memos) - - val adapter = CalendarAdapter(days, object : CalendarAdapter.OnDayClickListener { - override fun onDayClick(date: LocalDate, currentShift: String) { - showDaySettingsDialog(date, currentShift) - } - }, binding.cbShowHolidays.isChecked) - + val days = generateDaysForMonthWithData(currentViewMonth, currentViewTeam, factory, overrides, memos) + + // Calculate row count (5 or 6 rows) + val daysInMonth = currentViewMonth.lengthOfMonth() + val firstDayOfMonth = currentViewMonth.atDay(1).dayOfWeek.value % 7 + val actualDayCount = firstDayOfMonth + daysInMonth + val rowCount = if (actualDayCount <= 35) 5 else 6 + + val adapter = CalendarAdapter(days, object : CalendarAdapter.OnDayClickListener { + override fun onDayClick(date: LocalDate, currentShift: String) { + showDaySettingsDialog(date, currentShift) + } + }, binding.cbShowHolidays.isChecked, rowCount) + binding.calendarGrid.adapter = adapter binding.monthTitle.text = currentViewMonth.format(DateTimeFormatter.ofPattern("yyyy년 MM월")) @@ -314,10 +332,17 @@ class MainActivity : AppCompatActivity() { binding.todayStatusText.setTextColor(androidx.core.content.ContextCompat.getColor(this@MainActivity, R.color.warning_red)) } else { binding.todayStatusText.text = "오늘의 근무: $shiftForViewingTeam$teamSuffix" - binding.todayStatusText.setTextColor(androidx.core.content.ContextCompat.getColor(this@MainActivity, R.color.text_secondary)) - } - } + binding.todayStatusText.setTextColor(androidx.core.content.ContextCompat.getColor(this@MainActivity, R.color.text_secondary)) + } + // Update Annual Leave display + val annualLeave = withContext(Dispatchers.IO) { repo.getAnnualLeave() } + annualLeave?.let { + binding.tvAnnualLeave.text = "연차: ${String.format("%.1f", it.remainingDays)}" + } ?: run { + binding.tvAnnualLeave.text = "연차: --" + } + } updateOtherTeamsLayout(today, factory, prefs) } @@ -373,13 +398,13 @@ class MainActivity : AppCompatActivity() { setMargins(4, 0, 4, 0) } - setOnClickListener { - if (currentViewTeam != t) { - currentViewTeam = t - updateCalendar() - Toast.makeText(context, "${t}반 근무표를 표시합니다.", Toast.LENGTH_SHORT).show() - } - } + setOnClickListener { + if (currentViewTeam != t) { + currentViewTeam = t + updateCalendar() + showCustomToast(context, "${t}반 근무표를 표시합니다.") + } + } } rowLayout.addView(textView) }