2026-09-02 23:47:00 +03:00
|
|
|
package agzam.vyatsu.ui.schedule
|
|
|
|
|
|
|
|
|
|
import agzam.vyatsu.domain.ScheduleDates
|
|
|
|
|
import agzam.vyatsu.domain.model.Day
|
|
|
|
|
import agzam.vyatsu.domain.model.Schedule
|
|
|
|
|
import agzam.vyatsu.domain.repository.PreferencesRepository
|
|
|
|
|
import agzam.vyatsu.domain.repository.ScheduleRepository
|
|
|
|
|
import androidx.lifecycle.ViewModel
|
|
|
|
|
import androidx.lifecycle.viewModelScope
|
|
|
|
|
import kotlinx.coroutines.flow.MutableStateFlow
|
|
|
|
|
import kotlinx.coroutines.flow.StateFlow
|
|
|
|
|
import kotlinx.coroutines.flow.asStateFlow
|
|
|
|
|
import kotlinx.coroutines.launch
|
|
|
|
|
|
|
|
|
|
class ScheduleViewModel(
|
|
|
|
|
private val scheduleRepository: ScheduleRepository,
|
|
|
|
|
private val preferencesRepository: PreferencesRepository
|
|
|
|
|
) : ViewModel() {
|
|
|
|
|
|
|
|
|
|
private val _uiState = MutableStateFlow(ScheduleUiState())
|
|
|
|
|
val uiState: StateFlow<ScheduleUiState> = _uiState.asStateFlow()
|
|
|
|
|
|
|
|
|
|
private var currentGroupId: String? = null
|
|
|
|
|
|
|
|
|
|
init {
|
|
|
|
|
viewModelScope.launch {
|
|
|
|
|
val groupId = preferencesRepository.selectedGroupId()
|
|
|
|
|
if (groupId != null) {
|
|
|
|
|
selectGroup(groupId)
|
|
|
|
|
} else {
|
|
|
|
|
_uiState.value = _uiState.value.copy(noGroup = true)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun selectGroup(groupId: String) {
|
|
|
|
|
currentGroupId = groupId
|
|
|
|
|
viewModelScope.launch {
|
|
|
|
|
preferencesRepository.setSelectedGroup(groupId)
|
|
|
|
|
_uiState.value = _uiState.value.copy(noGroup = false)
|
|
|
|
|
|
|
|
|
|
launch {
|
|
|
|
|
scheduleRepository.observeSchedule(groupId).collect { schedule ->
|
|
|
|
|
currentGroupId?.let {
|
|
|
|
|
val days = schedule?.days.orEmpty()
|
|
|
|
|
val today = todayIndex(days)
|
|
|
|
|
val current = _uiState.value
|
|
|
|
|
val selected = current.selectedIndex.takeIf { i -> i in days.indices } ?: today
|
|
|
|
|
_uiState.value = current.copy(
|
|
|
|
|
schedule = schedule,
|
|
|
|
|
todayIndex = today,
|
|
|
|
|
selectedIndex = selected
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
launch {
|
2026-09-03 20:46:11 +03:00
|
|
|
syncIfMissingToday(groupId)
|
2026-09-02 23:47:00 +03:00
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-03 20:46:11 +03:00
|
|
|
private suspend fun syncIfMissingToday(groupId: String) {
|
|
|
|
|
val schedule = scheduleRepository.getSchedule(groupId)
|
|
|
|
|
val today = ScheduleDates.moscowToday()
|
|
|
|
|
val hasTodayPeriod = schedule?.periodOf(today) != null
|
|
|
|
|
if (hasTodayPeriod) return
|
|
|
|
|
_uiState.value = _uiState.value.copy(isSyncing = true)
|
|
|
|
|
scheduleRepository.sync(groupId)
|
|
|
|
|
_uiState.value = _uiState.value.copy(isSyncing = false)
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-02 23:47:00 +03:00
|
|
|
fun switchGroup() {
|
|
|
|
|
viewModelScope.launch {
|
|
|
|
|
currentGroupId = null
|
|
|
|
|
preferencesRepository.clearSelectedGroup()
|
|
|
|
|
_uiState.value = _uiState.value.copy(noGroup = true)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun refresh() {
|
|
|
|
|
val groupId = currentGroupId ?: return
|
|
|
|
|
viewModelScope.launch {
|
|
|
|
|
_uiState.value = _uiState.value.copy(isRefreshing = true)
|
|
|
|
|
scheduleRepository.sync(groupId)
|
|
|
|
|
val current = _uiState.value
|
|
|
|
|
val days = current.schedule?.days.orEmpty()
|
|
|
|
|
val today = todayIndex(days)
|
|
|
|
|
_uiState.value = current.copy(
|
|
|
|
|
isRefreshing = false,
|
|
|
|
|
todayIndex = today,
|
|
|
|
|
selectedIndex = current.selectedIndex.takeIf { it in days.indices } ?: today
|
|
|
|
|
)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun selectDay(index: Int) {
|
|
|
|
|
val days = _uiState.value.schedule?.days.orEmpty()
|
|
|
|
|
if (index !in days.indices) return
|
|
|
|
|
_uiState.value = _uiState.value.copy(selectedIndex = index)
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-03 19:41:26 +03:00
|
|
|
fun clearAll() {
|
|
|
|
|
val groupId = currentGroupId ?: return
|
|
|
|
|
viewModelScope.launch {
|
|
|
|
|
scheduleRepository.clearAll(groupId)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
fun clearSelectedPeriod() {
|
|
|
|
|
val state = _uiState.value
|
|
|
|
|
val schedule = state.schedule ?: return
|
|
|
|
|
val day = schedule.days.getOrNull(state.selectedIndex) ?: return
|
|
|
|
|
val period = schedule.periodOf(day.date) ?: return
|
|
|
|
|
viewModelScope.launch {
|
|
|
|
|
scheduleRepository.clearPeriod(schedule.groupId, period)
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-09-02 23:47:00 +03:00
|
|
|
private fun todayIndex(days: List<Day>): Int {
|
|
|
|
|
if (days.isEmpty()) return 0
|
|
|
|
|
val today = ScheduleDates.moscowToday()
|
|
|
|
|
val exact = days.indexOfFirst { it.date == today }
|
|
|
|
|
if (exact >= 0) return exact
|
|
|
|
|
val next = days.indexOfFirst { !it.date.isBefore(today) }
|
|
|
|
|
return if (next >= 0) next else days.lastIndex
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
data class ScheduleUiState(
|
|
|
|
|
val noGroup: Boolean = false,
|
|
|
|
|
val isRefreshing: Boolean = false,
|
|
|
|
|
val isSyncing: Boolean = false,
|
|
|
|
|
val schedule: Schedule? = null,
|
|
|
|
|
val todayIndex: Int = 0,
|
|
|
|
|
val selectedIndex: Int = 0
|
|
|
|
|
)
|