Skip to content

Commit

Permalink
Merge pull request #101 from uswLectureEvaluation/feature/#99-timetab…
Browse files Browse the repository at this point in the history
…le-list-cell-edit

Feature/#99 timetable list cell edit
  • Loading branch information
jinukeu authored Jan 17, 2024
2 parents 363660f + 030ff5e commit 24fb015
Show file tree
Hide file tree
Showing 41 changed files with 1,112 additions and 283 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ import com.suwiki.core.database.model.TimetableEntity

@Dao
interface TimeTableDao {
@Query("SELECT * FROM TimetableEntity")
@Query("SELECT * FROM TimetableEntity ORDER BY createTime DESC")
fun getAll(): List<TimetableEntity>

@Query("SELECT * FROM TimetableEntity WHERE createTime = :createTime")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import kotlinx.serialization.Serializable
@Stable
@Serializable
data class Timetable(
val createTime: Long,
val year: String,
val semester: String,
val name: String,
val cellList: List<TimetableCell>,
val createTime: Long = 0,
val year: String = "",
val semester: String = "",
val name: String = "",
val cellList: List<TimetableCell> = emptyList(),
)
10 changes: 10 additions & 0 deletions core/ui/src/main/java/com/suwiki/core/ui/extension/Etc.kt
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
package com.suwiki.core.ui.extension

import android.content.Context
import android.content.pm.PackageInfo
import androidx.core.content.pm.PackageInfoCompat

internal inline fun <T> T.runIf(condition: Boolean, run: T.() -> T) = if (condition) {
run()
} else {
this
}

val Context.versionCode: Long
get() {
val pi: PackageInfo = packageManager.getPackageInfo(packageName, 0)
return PackageInfoCompat.getLongVersionCode(pi)
}
3 changes: 3 additions & 0 deletions core/ui/src/main/res/values/strings.xml
Original file line number Diff line number Diff line change
Expand Up @@ -72,4 +72,7 @@
<string name="word_apply">적용</string>
<string name="word_add">추가</string>
<string name="word_delete">삭제</string>
<string name="word_do_delete">삭제하기</string>
<string name="word_do_edit">수정하기</string>
<string name="word_cancel">취소</string>
</resources>
Original file line number Diff line number Diff line change
Expand Up @@ -18,4 +18,7 @@ interface LocalTimetableDataSource {

suspend fun updateTimetable(data: Timetable)
suspend fun insertTimetable(data: Timetable)

suspend fun getTimetableCellType(): Flow<String>
suspend fun setTimetableCellType(type: String)
}
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import com.suwiki.core.model.exception.TimetableCellOverlapException
import com.suwiki.core.model.exception.TimetableCellPeriodInvalidException
import com.suwiki.core.model.timetable.Timetable
import com.suwiki.core.model.timetable.TimetableCell
import com.suwiki.core.model.timetable.TimetableDay
import com.suwiki.data.timetable.datasource.LocalTimetableDataSource
import com.suwiki.domain.timetable.repository.TimetableRepository
import kotlinx.coroutines.flow.firstOrNull
Expand Down Expand Up @@ -63,6 +64,7 @@ class TimetableRepositoryImpl @Inject constructor(
override suspend fun insertTimetableCell(cellList: List<TimetableCell>) {
val timetable = getMainTimetable()!!
checkPeriodInvalid(cellList)
checkCellOverlap(cellList, cellList)
checkCellOverlap(cellList, timetable.cellList)
localTimetableDataSource.updateTimetable(
timetable.copy(
Expand All @@ -71,25 +73,28 @@ class TimetableRepositoryImpl @Inject constructor(
)
}

override suspend fun deleteTimetableCell(cell: TimetableCell) {
override suspend fun deleteTimetableCell(cell: TimetableCell): Timetable {
val timetable = getMainTimetable()!!
.run {
copy(cellList = cellList.minus(cell))
}
localTimetableDataSource.updateTimetable(
timetable.copy(
cellList = timetable.cellList.minus(cell),
),
timetable,
)
return timetable
}

override suspend fun updateTimetableCell(cell: TimetableCell) {
override suspend fun updateTimetableCell(oldCellId: String, cellList: List<TimetableCell>) {
val timetable = getMainTimetable()!!
val oldCell = timetable.cellList.find { it.id == cell.id }!!
val tempCellList = timetable.cellList.minus(oldCell)
val toInsertCell = listOf(cell)
checkPeriodInvalid(toInsertCell)
checkCellOverlap(toInsertCell, tempCellList)
val tempCellList = timetable.cellList.filter { it.id != oldCellId }

checkPeriodInvalid(cellList)
checkCellOverlap(cellList, cellList)
checkCellOverlap(cellList, tempCellList)

localTimetableDataSource.updateTimetable(
timetable.copy(
cellList = tempCellList.plus(cell),
cellList = tempCellList.plus(cellList),
),
)
}
Expand All @@ -102,7 +107,7 @@ class TimetableRepositoryImpl @Inject constructor(
private fun checkPeriodInvalid(
cellList: List<TimetableCell>,
) {
cellList.forEach { cell ->
cellList.filter { it.day != TimetableDay.E_LEARNING }.forEach { cell ->
val isNotValid = cell.startPeriod > cell.endPeriod ||
cell.startPeriod !in 1..15 ||
cell.endPeriod !in 1..15
Expand All @@ -122,6 +127,8 @@ class TimetableRepositoryImpl @Inject constructor(
toInsertCellList.forEach { toInsertCell ->
currentCellList
.filter { it.day == toInsertCell.day }
.filter { it.id != toInsertCell.id }
.filter { it.day != TimetableDay.E_LEARNING }
.forEach { sameDayCell ->
val isOverlap = toInsertCell.startPeriod in sameDayCell.startPeriod..sameDayCell.endPeriod ||
toInsertCell.endPeriod in sameDayCell.startPeriod..sameDayCell.endPeriod ||
Expand All @@ -138,4 +145,12 @@ class TimetableRepositoryImpl @Inject constructor(
}
}
}

override suspend fun getTimetableCellType(): String {
return localTimetableDataSource.getTimetableCellType().firstOrNull() ?: ""
}

override suspend fun setTimetableCellType(type: String) {
localTimetableDataSource.setTimetableCellType(type)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,10 @@ interface TimetableRepository {

suspend fun insertTimetableCell(cellList: List<TimetableCell>)

suspend fun deleteTimetableCell(cell: TimetableCell)
suspend fun deleteTimetableCell(cell: TimetableCell): Timetable

suspend fun updateTimetableCell(cell: TimetableCell)
suspend fun updateTimetableCell(oldCellId: String, cellList: List<TimetableCell>)

suspend fun getTimetableCellType(): String
suspend fun setTimetableCellType(type: String)
}
Original file line number Diff line number Diff line change
@@ -1,16 +1,15 @@
package com.suwiki.domain.timetable.usecase

import com.suwiki.core.common.runCatchingIgnoreCancelled
import com.suwiki.core.model.timetable.Timetable
import com.suwiki.core.model.timetable.TimetableCell
import com.suwiki.domain.timetable.repository.TimetableRepository
import javax.inject.Inject

class DeleteTimetableCellUseCase @Inject constructor(
private val timetableRepository: TimetableRepository,
) {
suspend operator fun invoke(cell: TimetableCell): Result<Unit> = runCatchingIgnoreCancelled {
timetableRepository.deleteTimetableCell(
cell = cell,
)
suspend operator fun invoke(cell: TimetableCell): Result<Timetable> = runCatchingIgnoreCancelled {
timetableRepository.deleteTimetableCell(cell = cell)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,12 @@ class DeleteTimetableUseCase @Inject constructor(
suspend operator fun invoke(timetable: Timetable): Result<Unit> = runCatchingIgnoreCancelled {
with(timetableRepository) {
deleteTimetable(timetable)
val firstTimetableCreateTime = timetableRepository.getAllTimetable().firstOrNull()?.createTime ?: 0L
timetableRepository.setMainTimetableCreateTime(firstTimetableCreateTime)

val mainTimetableCreateTime = getMainTimetableCreateTime()
if (mainTimetableCreateTime != timetable.createTime) return@runCatchingIgnoreCancelled

val firstTimetableCreateTime = getAllTimetable().firstOrNull()?.createTime ?: 0L
setMainTimetableCreateTime(firstTimetableCreateTime)
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.suwiki.domain.timetable.usecase

import com.suwiki.core.common.runCatchingIgnoreCancelled
import com.suwiki.domain.timetable.repository.TimetableRepository
import javax.inject.Inject

class GetTimetableCellTypeUseCase @Inject constructor(
private val timetableRepository: TimetableRepository,
) {
suspend operator fun invoke() = runCatchingIgnoreCancelled {
timetableRepository.getTimetableCellType()
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
package com.suwiki.domain.timetable.usecase

import com.suwiki.core.common.runCatchingIgnoreCancelled
import com.suwiki.domain.timetable.repository.TimetableRepository
import javax.inject.Inject

class SetTimetableCellTypeUseCase @Inject constructor(
private val timetableRepository: TimetableRepository,
) {
suspend operator fun invoke(type: String) = runCatchingIgnoreCancelled {
timetableRepository.setTimetableCellType(type)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,12 @@ import javax.inject.Inject
class UpdateTimetableCellUseCase @Inject constructor(
private val timetableRepository: TimetableRepository,
) {
suspend operator fun invoke(cell: TimetableCell): Result<Unit> = runCatchingIgnoreCancelled {
timetableRepository.updateTimetableCell(
cell = cell,
)
suspend operator fun invoke(param: Param): Result<Unit> = runCatchingIgnoreCancelled {
timetableRepository.updateTimetableCell(oldCellId = param.oldCellId, cellList = param.cellList)
}

data class Param(
val oldCellId: String,
val cellList: List<TimetableCell>,
)
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,6 @@ import androidx.navigation.NavOptions
import androidx.navigation.compose.currentBackStackEntryAsState
import androidx.navigation.compose.rememberNavController
import androidx.navigation.navOptions
import com.suwiki.core.model.timetable.OpenLecture
import com.suwiki.feature.lectureevaluation.editor.navigation.navigateMyExamEvaluation
import com.suwiki.feature.lectureevaluation.editor.navigation.navigateMyLectureEvaluation
import com.suwiki.feature.lectureevaluation.my.navigation.navigateMyEvaluation
Expand All @@ -27,10 +26,13 @@ import com.suwiki.feature.openmajor.navigation.navigateOpenMajor
import com.suwiki.feature.signup.navigation.navigateSignup
import com.suwiki.feature.signup.navigation.navigateSignupComplete
import com.suwiki.feature.timetable.navigation.TimetableRoute
import com.suwiki.feature.timetable.navigation.navigateAddCell
import com.suwiki.feature.timetable.navigation.navigateCreateTimetable
import com.suwiki.feature.timetable.navigation.argument.CellEditorArgument
import com.suwiki.feature.timetable.navigation.argument.TimetableEditorArgument
import com.suwiki.feature.timetable.navigation.navigateCellEditor
import com.suwiki.feature.timetable.navigation.navigateOpenLecture
import com.suwiki.feature.timetable.navigation.navigateTimetable
import com.suwiki.feature.timetable.navigation.navigateTimetableEditor
import com.suwiki.feature.timetable.navigation.navigateTimetableList

internal class MainNavigator(
val navController: NavHostController,
Expand Down Expand Up @@ -118,15 +120,19 @@ internal class MainNavigator(
navController.navigateOpenMajor(selectedOpenMajor)
}

fun navigateAddCell(openLecture: OpenLecture) {
navController.navigateAddCell(openLecture)
fun navigateCellEditor(argument: CellEditorArgument) {
navController.navigateCellEditor(argument)
}

fun navigateCreateTimetable() {
navController.navigateCreateTimetable()
fun navigateTimetableEditor(argument: TimetableEditorArgument = TimetableEditorArgument()) {
navController.navigateTimetableEditor(argument)
}

fun navigateAddTimetableCell() {
fun navigateTimetableList() {
navController.navigateTimetableList()
}

fun navigateOpenLecture() {
navController.navigateOpenLecture()
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -95,12 +95,13 @@ internal fun MainScreen(
padding = innerPadding,
argumentName = OpenMajorRoute.ARGUMENT_NAME,
popBackStack = navigator::popBackStackIfNotHome,
navigateCreateTimetable = navigator::navigateCreateTimetable,
navigateOpenLecture = navigator::navigateAddTimetableCell,
navigateTimetableEditor = navigator::navigateTimetableEditor,
navigateTimetableList = navigator::navigateTimetableList,
navigateOpenLecture = navigator::navigateOpenLecture,
handleException = viewModel::handleException,
onShowToast = viewModel::onShowToast,
navigateOpenMajor = navigator::navigateOpenMajor,
navigateAddCell = navigator::navigateAddCell,
navigateCellEditor = navigator::navigateCellEditor,
)

lectureEvaluationNavGraph(
Expand Down

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
package com.suwiki.feature.timetable.celleditor

import com.suwiki.core.model.timetable.TimetableCellColor
import com.suwiki.core.model.timetable.TimetableDay
import com.suwiki.feature.timetable.navigation.argument.CellArgument
import com.suwiki.feature.timetable.navigation.argument.CellEditorArgument
import kotlinx.collections.immutable.PersistentList
import kotlinx.collections.immutable.persistentListOf
import kotlinx.collections.immutable.toPersistentList

data class CellEditorState(
val lectureName: String = "",
val professorName: String = "",
val cellStateList: PersistentList<CellState> = persistentListOf(CellState()),
val selectedTimetableCellColor: TimetableCellColor = TimetableCellColor.GRAY_DARK,
)

data class CellState(
val location: String = "",
val day: TimetableDay = TimetableDay.MON,
val startPeriod: String = "",
val endPeriod: String = "",
)

internal fun CellArgument.toState() = CellState(
location = location,
day = day,
startPeriod = startPeriod,
endPeriod = endPeriod,
)

internal fun CellEditorArgument.toState() = CellEditorState(
lectureName = name,
professorName = professorName,
cellStateList = cellList.map { it.toState() }.toPersistentList(),
selectedTimetableCellColor = timetableCellColor,
)

sealed interface CellEditorSideEffect {
data object PopBackStack : CellEditorSideEffect
data class HandleException(val throwable: Throwable) : CellEditorSideEffect
data class ShowToast(val msg: String) : CellEditorSideEffect
data object ShowAddSuccessCellToast : CellEditorSideEffect
data object ShowEditSuccessCellToast : CellEditorSideEffect
data object ShowNeedLectureNameToast : CellEditorSideEffect
data object ShowNeedProfessorNameToast : CellEditorSideEffect
data object ShowNeedLocationToast : CellEditorSideEffect
}
Loading

0 comments on commit 24fb015

Please sign in to comment.