#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
	
	 brreynie
						brreynie