#21 basic subject list
This commit is contained in:
		
							parent
							
								
									76e69dd03c
								
							
						
					
					
						commit
						d03775000a
					
				
					 16 changed files with 228 additions and 22 deletions
				
			
		| 
						 | 
				
			
			@ -40,6 +40,7 @@ import be.ugent.sel.studeez.screens.session.SessionRoute
 | 
			
		|||
import be.ugent.sel.studeez.screens.session_recap.SessionRecapRoute
 | 
			
		||||
import be.ugent.sel.studeez.screens.sign_up.SignUpRoute
 | 
			
		||||
import be.ugent.sel.studeez.screens.splash.SplashRoute
 | 
			
		||||
import be.ugent.sel.studeez.screens.tasks.TaskRoute
 | 
			
		||||
import be.ugent.sel.studeez.screens.timer_overview.TimerOverviewRoute
 | 
			
		||||
import be.ugent.sel.studeez.screens.timer_selection.TimerSelectionRoute
 | 
			
		||||
import be.ugent.sel.studeez.ui.theme.StudeezTheme
 | 
			
		||||
| 
						 | 
				
			
			@ -145,7 +146,14 @@ fun StudeezNavGraph(
 | 
			
		|||
            )
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // TODO Tasks screen
 | 
			
		||||
        composable(StudeezDestinations.TASKS_SCREEN) {
 | 
			
		||||
            TaskRoute(
 | 
			
		||||
                open = open,
 | 
			
		||||
                viewModel = hiltViewModel(),
 | 
			
		||||
                drawerActions = drawerActions,
 | 
			
		||||
                navigationBarActions = navigationBarActions,
 | 
			
		||||
            )
 | 
			
		||||
        }
 | 
			
		||||
        // TODO Sessions screen
 | 
			
		||||
 | 
			
		||||
        composable(StudeezDestinations.PROFILE_SCREEN) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,19 @@
 | 
			
		|||
package be.ugent.sel.studeez.common.composable
 | 
			
		||||
 | 
			
		||||
import androidx.compose.material.Text
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.ui.tooling.preview.Preview
 | 
			
		||||
import be.ugent.sel.studeez.data.local.models.task.Subject
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun SubjectEntry(
 | 
			
		||||
    subject: Subject,
 | 
			
		||||
) {
 | 
			
		||||
    Text(text = subject.name)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Preview
 | 
			
		||||
@Composable
 | 
			
		||||
fun SubjectEntryPreview() {
 | 
			
		||||
    SubjectEntry(subject = Subject(name = "Test Subject"))
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,16 +1,15 @@
 | 
			
		|||
package be.ugent.sel.studeez.common.composable.navbar
 | 
			
		||||
 | 
			
		||||
import be.ugent.sel.studeez.domain.AccountDAO
 | 
			
		||||
import be.ugent.sel.studeez.domain.LogService
 | 
			
		||||
import be.ugent.sel.studeez.navigation.StudeezDestinations.HOME_SCREEN
 | 
			
		||||
import be.ugent.sel.studeez.navigation.StudeezDestinations.PROFILE_SCREEN
 | 
			
		||||
import be.ugent.sel.studeez.navigation.StudeezDestinations.TASKS_SCREEN
 | 
			
		||||
import be.ugent.sel.studeez.screens.StudeezViewModel
 | 
			
		||||
import dagger.hilt.android.lifecycle.HiltViewModel
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
@HiltViewModel
 | 
			
		||||
class NavigationBarViewModel @Inject constructor(
 | 
			
		||||
    private val accountDAO: AccountDAO,
 | 
			
		||||
    logService: LogService
 | 
			
		||||
) : StudeezViewModel(logService) {
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -19,7 +18,7 @@ class NavigationBarViewModel @Inject constructor(
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    fun onTasksClick(open: (String) -> Unit) {
 | 
			
		||||
        // TODO
 | 
			
		||||
        open(TASKS_SCREEN)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun onSessionsClick(open: (String) -> Unit) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,4 +7,4 @@ data class SessionReport(
 | 
			
		|||
    @DocumentId val id: String = "",
 | 
			
		||||
    val studyTime: Int = 0,
 | 
			
		||||
    val endTime: Timestamp = Timestamp(0, 0)
 | 
			
		||||
    )
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,11 @@
 | 
			
		|||
package be.ugent.sel.studeez.data.local.models.task
 | 
			
		||||
 | 
			
		||||
import com.google.firebase.firestore.DocumentId
 | 
			
		||||
 | 
			
		||||
data class Subject(
 | 
			
		||||
    @DocumentId val id: String = "",
 | 
			
		||||
    val name: String = "",
 | 
			
		||||
    val tasks: List<Task> = mutableListOf(),
 | 
			
		||||
    val time: Int = 0,
 | 
			
		||||
    val color: Int = 0,
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,9 @@
 | 
			
		|||
package be.ugent.sel.studeez.data.local.models.task
 | 
			
		||||
 | 
			
		||||
import com.google.firebase.firestore.DocumentId
 | 
			
		||||
 | 
			
		||||
data class Task(
 | 
			
		||||
    @DocumentId val id: String = "",
 | 
			
		||||
    val name: String = "",
 | 
			
		||||
    val completed: Boolean = false,
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -10,15 +10,24 @@ import dagger.hilt.components.SingletonComponent
 | 
			
		|||
@Module
 | 
			
		||||
@InstallIn(SingletonComponent::class)
 | 
			
		||||
abstract class DatabaseModule {
 | 
			
		||||
    @Binds abstract fun provideAccountDAO(impl: FirebaseAccountDAO): AccountDAO
 | 
			
		||||
    @Binds
 | 
			
		||||
    abstract fun provideAccountDAO(impl: FirebaseAccountDAO): AccountDAO
 | 
			
		||||
 | 
			
		||||
    @Binds abstract fun provideUserDAO(impl: FirebaseUserDAO): UserDAO
 | 
			
		||||
    @Binds
 | 
			
		||||
    abstract fun provideUserDAO(impl: FirebaseUserDAO): UserDAO
 | 
			
		||||
 | 
			
		||||
    @Binds abstract fun provideTimerDAO(impl: FirebaseTimerDAO): TimerDAO
 | 
			
		||||
    @Binds
 | 
			
		||||
    abstract fun provideTimerDAO(impl: FirebaseTimerDAO): TimerDAO
 | 
			
		||||
 | 
			
		||||
    @Binds abstract fun provideLogService(impl: LogServiceImpl): LogService
 | 
			
		||||
    @Binds
 | 
			
		||||
    abstract fun provideLogService(impl: LogServiceImpl): LogService
 | 
			
		||||
 | 
			
		||||
    @Binds abstract fun provideConfigurationService(impl: FirebaseConfigurationService): ConfigurationService
 | 
			
		||||
    @Binds
 | 
			
		||||
    abstract fun provideConfigurationService(impl: FirebaseConfigurationService): ConfigurationService
 | 
			
		||||
 | 
			
		||||
    @Binds abstract fun provideSessionDAO(impl: FireBaseSessionDAO): SessionDAO
 | 
			
		||||
    @Binds
 | 
			
		||||
    abstract fun provideSessionDAO(impl: FireBaseSessionDAO): SessionDAO
 | 
			
		||||
 | 
			
		||||
    @Binds
 | 
			
		||||
    abstract fun provideSubjectDAO(impl: FireBaseSubjectDAO): SubjectDAO
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										13
									
								
								app/src/main/java/be/ugent/sel/studeez/domain/SubjectDAO.kt
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								app/src/main/java/be/ugent/sel/studeez/domain/SubjectDAO.kt
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,13 @@
 | 
			
		|||
package be.ugent.sel.studeez.domain
 | 
			
		||||
 | 
			
		||||
import be.ugent.sel.studeez.data.local.models.task.Subject
 | 
			
		||||
import kotlinx.coroutines.flow.Flow
 | 
			
		||||
 | 
			
		||||
interface SubjectDAO {
 | 
			
		||||
 | 
			
		||||
    fun getSubjects(): Flow<List<Subject>>
 | 
			
		||||
 | 
			
		||||
    fun saveSubject(newSubject: Subject)
 | 
			
		||||
 | 
			
		||||
    fun deleteSubject(oldSubject: Subject)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,8 +1,8 @@
 | 
			
		|||
package be.ugent.sel.studeez.domain.implementation
 | 
			
		||||
 | 
			
		||||
object FirebaseCollectionRoutes {
 | 
			
		||||
object FireBaseCollections {
 | 
			
		||||
    const val SESSION_COLLECTION = "sessions"
 | 
			
		||||
    const val USER_COLLECTION = "users"
 | 
			
		||||
    const val TIMER_COLLECTION = "timers"
 | 
			
		||||
 | 
			
		||||
    const val SUBJECT_COLLECTION = "subjects"
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -31,8 +31,7 @@ class FireBaseSessionDAO @Inject constructor(
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    private fun currentUserSessionsCollection(): CollectionReference =
 | 
			
		||||
        firestore.collection(FirebaseCollectionRoutes.USER_COLLECTION)
 | 
			
		||||
        firestore.collection(FireBaseCollections.USER_COLLECTION)
 | 
			
		||||
            .document(auth.currentUserId)
 | 
			
		||||
            .collection(FirebaseCollectionRoutes.SESSION_COLLECTION)
 | 
			
		||||
 | 
			
		||||
            .collection(FireBaseCollections.SESSION_COLLECTION)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,35 @@
 | 
			
		|||
package be.ugent.sel.studeez.domain.implementation
 | 
			
		||||
 | 
			
		||||
import be.ugent.sel.studeez.data.local.models.task.Subject
 | 
			
		||||
import be.ugent.sel.studeez.domain.AccountDAO
 | 
			
		||||
import be.ugent.sel.studeez.domain.SubjectDAO
 | 
			
		||||
import com.google.firebase.firestore.CollectionReference
 | 
			
		||||
import com.google.firebase.firestore.FirebaseFirestore
 | 
			
		||||
import com.google.firebase.firestore.ktx.snapshots
 | 
			
		||||
import kotlinx.coroutines.flow.Flow
 | 
			
		||||
import kotlinx.coroutines.flow.map
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
class FireBaseSubjectDAO @Inject constructor(
 | 
			
		||||
    private val firestore: FirebaseFirestore,
 | 
			
		||||
    private val auth: AccountDAO,
 | 
			
		||||
) : SubjectDAO {
 | 
			
		||||
    override fun getSubjects(): Flow<List<Subject>> {
 | 
			
		||||
        return currentUserSubjectsCollection()
 | 
			
		||||
            .snapshots()
 | 
			
		||||
            .map { it.toObjects(Subject::class.java) }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun saveSubject(newSubject: Subject) {
 | 
			
		||||
        currentUserSubjectsCollection().add(newSubject)
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    override fun deleteSubject(oldSubject: Subject) {
 | 
			
		||||
        TODO("Not yet implemented")
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private fun currentUserSubjectsCollection(): CollectionReference =
 | 
			
		||||
        firestore.collection(FireBaseCollections.USER_COLLECTION)
 | 
			
		||||
            .document(auth.currentUserId)
 | 
			
		||||
            .collection(FireBaseCollections.SUBJECT_COLLECTION)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -1,11 +1,9 @@
 | 
			
		|||
package be.ugent.sel.studeez.domain.implementation
 | 
			
		||||
 | 
			
		||||
import be.ugent.sel.studeez.data.local.models.timer_info.*
 | 
			
		||||
import be.ugent.sel.studeez.data.local.models.timer_info.TimerType.*
 | 
			
		||||
import be.ugent.sel.studeez.domain.AccountDAO
 | 
			
		||||
import be.ugent.sel.studeez.domain.TimerDAO
 | 
			
		||||
import com.google.firebase.firestore.CollectionReference
 | 
			
		||||
import com.google.firebase.firestore.DocumentSnapshot
 | 
			
		||||
import com.google.firebase.firestore.FirebaseFirestore
 | 
			
		||||
import com.google.firebase.firestore.ktx.snapshots
 | 
			
		||||
import kotlinx.coroutines.flow.Flow
 | 
			
		||||
| 
						 | 
				
			
			@ -50,8 +48,8 @@ class FirebaseTimerDAO @Inject constructor(
 | 
			
		|||
    }
 | 
			
		||||
 | 
			
		||||
    private fun currentUserTimersCollection(): CollectionReference =
 | 
			
		||||
        firestore.collection(FirebaseCollectionRoutes.USER_COLLECTION)
 | 
			
		||||
        firestore.collection(FireBaseCollections.USER_COLLECTION)
 | 
			
		||||
            .document(auth.currentUserId)
 | 
			
		||||
            .collection(FirebaseCollectionRoutes.TIMER_COLLECTION)
 | 
			
		||||
            .collection(FireBaseCollections.TIMER_COLLECTION)
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -10,7 +10,7 @@ object StudeezDestinations {
 | 
			
		|||
    const val TIMER_SELECTION_SCREEN = "timer_selection"
 | 
			
		||||
    const val SESSION_SCREEN = "session"
 | 
			
		||||
    const val SESSION_RECAP = "session_recap"
 | 
			
		||||
 //    const val TASKS_SCREEN = "tasks"
 | 
			
		||||
     const val TASKS_SCREEN = "tasks"
 | 
			
		||||
 //    const val SESSIONS_SCREEN = "sessions"
 | 
			
		||||
    const val PROFILE_SCREEN = "profile"
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -0,0 +1,77 @@
 | 
			
		|||
package be.ugent.sel.studeez.screens.tasks
 | 
			
		||||
 | 
			
		||||
import androidx.compose.foundation.layout.Column
 | 
			
		||||
import androidx.compose.foundation.lazy.LazyColumn
 | 
			
		||||
import androidx.compose.foundation.lazy.items
 | 
			
		||||
import androidx.compose.material.Button
 | 
			
		||||
import androidx.compose.material.Text
 | 
			
		||||
import androidx.compose.runtime.Composable
 | 
			
		||||
import androidx.compose.runtime.collectAsState
 | 
			
		||||
import androidx.compose.ui.tooling.preview.Preview
 | 
			
		||||
import be.ugent.sel.studeez.R
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.PrimaryScreenTemplate
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.SubjectEntry
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.drawer.DrawerActions
 | 
			
		||||
import be.ugent.sel.studeez.common.composable.navbar.NavigationBarActions
 | 
			
		||||
import be.ugent.sel.studeez.data.local.models.task.Subject
 | 
			
		||||
import be.ugent.sel.studeez.resources
 | 
			
		||||
import kotlinx.coroutines.flow.Flow
 | 
			
		||||
import kotlinx.coroutines.flow.flowOf
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun TaskRoute(
 | 
			
		||||
    open: (String) -> Unit,
 | 
			
		||||
    viewModel: TaskViewModel,
 | 
			
		||||
    drawerActions: DrawerActions,
 | 
			
		||||
    navigationBarActions: NavigationBarActions,
 | 
			
		||||
) {
 | 
			
		||||
    TaskScreen(
 | 
			
		||||
        drawerActions = drawerActions,
 | 
			
		||||
        navigationBarActions = navigationBarActions,
 | 
			
		||||
        addSubject = { viewModel.addSubject() },
 | 
			
		||||
    ) { viewModel.getSubjects() }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun TaskScreen(
 | 
			
		||||
    drawerActions: DrawerActions,
 | 
			
		||||
    navigationBarActions: NavigationBarActions,
 | 
			
		||||
    addSubject: () -> Unit,
 | 
			
		||||
    getSubjects: () -> Flow<List<Subject>>,
 | 
			
		||||
) {
 | 
			
		||||
    PrimaryScreenTemplate(
 | 
			
		||||
        title = resources().getString(R.string.tasks),
 | 
			
		||||
        drawerActions = drawerActions,
 | 
			
		||||
        navigationBarActions = navigationBarActions,
 | 
			
		||||
        barAction = {},
 | 
			
		||||
    ) {
 | 
			
		||||
        val subjects = getSubjects().collectAsState(initial = emptyList())
 | 
			
		||||
        Column {
 | 
			
		||||
            LazyColumn {
 | 
			
		||||
                items(subjects.value) {
 | 
			
		||||
                    SubjectEntry(subject = it)
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            AddSubjectButton(onClick = addSubject)
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Composable
 | 
			
		||||
fun AddSubjectButton(
 | 
			
		||||
    onClick: () -> Unit,
 | 
			
		||||
) {
 | 
			
		||||
    Button(onClick = onClick) {
 | 
			
		||||
        Text(text = "Test Button")
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@Preview
 | 
			
		||||
@Composable
 | 
			
		||||
fun TaskScreenPreview() {
 | 
			
		||||
    TaskScreen(
 | 
			
		||||
        drawerActions = DrawerActions({}, {}, {}, {}, {}),
 | 
			
		||||
        navigationBarActions = NavigationBarActions({ false }, {}, {}, {}, {}),
 | 
			
		||||
        {},
 | 
			
		||||
    ) { flowOf() }
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -0,0 +1,30 @@
 | 
			
		|||
package be.ugent.sel.studeez.screens.tasks
 | 
			
		||||
 | 
			
		||||
import be.ugent.sel.studeez.data.local.models.task.Subject
 | 
			
		||||
import be.ugent.sel.studeez.domain.LogService
 | 
			
		||||
import be.ugent.sel.studeez.domain.SubjectDAO
 | 
			
		||||
import be.ugent.sel.studeez.screens.StudeezViewModel
 | 
			
		||||
import dagger.hilt.android.lifecycle.HiltViewModel
 | 
			
		||||
import kotlinx.coroutines.flow.Flow
 | 
			
		||||
import javax.inject.Inject
 | 
			
		||||
 | 
			
		||||
@HiltViewModel
 | 
			
		||||
class TaskViewModel @Inject constructor(
 | 
			
		||||
    private val subjectDAO: SubjectDAO,
 | 
			
		||||
    logService: LogService,
 | 
			
		||||
) : StudeezViewModel(logService) {
 | 
			
		||||
    fun addSubject() {
 | 
			
		||||
        subjectDAO.saveSubject(
 | 
			
		||||
            Subject(
 | 
			
		||||
                name = "Test Subject",
 | 
			
		||||
                tasks = listOf(),
 | 
			
		||||
                time = 0,
 | 
			
		||||
                color = 0,
 | 
			
		||||
            )
 | 
			
		||||
        )
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    fun getSubjects(): Flow<List<Subject>> {
 | 
			
		||||
        return subjectDAO.getSubjects()
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in a new issue