#21 basic subject list
This commit is contained in:
		
							parent
							
								
									76e69dd03c
								
							
						
					
					
						commit
						d03775000a
					
				
					 16 changed files with 228 additions and 22 deletions
				
			
		
							
								
								
									
										1
									
								
								.idea/misc.xml
									
										
									
										generated
									
									
									
								
							
							
						
						
									
										1
									
								
								.idea/misc.xml
									
										
									
										generated
									
									
									
								
							|  | @ -1,4 +1,3 @@ | ||||||
| <?xml version="1.0" encoding="UTF-8"?> |  | ||||||
| <project version="4"> | <project version="4"> | ||||||
|   <component name="ExternalStorageConfigurationManager" enabled="true" /> |   <component name="ExternalStorageConfigurationManager" enabled="true" /> | ||||||
|   <component name="ProjectRootManager" version="2" languageLevel="JDK_17_PREVIEW" project-jdk-name="jbr-17" project-jdk-type="JavaSDK"> |   <component name="ProjectRootManager" version="2" languageLevel="JDK_17_PREVIEW" project-jdk-name="jbr-17" project-jdk-type="JavaSDK"> | ||||||
|  |  | ||||||
|  | @ -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.session_recap.SessionRecapRoute | ||||||
| import be.ugent.sel.studeez.screens.sign_up.SignUpRoute | import be.ugent.sel.studeez.screens.sign_up.SignUpRoute | ||||||
| import be.ugent.sel.studeez.screens.splash.SplashRoute | 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_overview.TimerOverviewRoute | ||||||
| import be.ugent.sel.studeez.screens.timer_selection.TimerSelectionRoute | import be.ugent.sel.studeez.screens.timer_selection.TimerSelectionRoute | ||||||
| import be.ugent.sel.studeez.ui.theme.StudeezTheme | 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 |         // TODO Sessions screen | ||||||
| 
 | 
 | ||||||
|         composable(StudeezDestinations.PROFILE_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 | 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.domain.LogService | ||||||
| import be.ugent.sel.studeez.navigation.StudeezDestinations.HOME_SCREEN | 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.PROFILE_SCREEN | ||||||
|  | import be.ugent.sel.studeez.navigation.StudeezDestinations.TASKS_SCREEN | ||||||
| import be.ugent.sel.studeez.screens.StudeezViewModel | import be.ugent.sel.studeez.screens.StudeezViewModel | ||||||
| import dagger.hilt.android.lifecycle.HiltViewModel | import dagger.hilt.android.lifecycle.HiltViewModel | ||||||
| import javax.inject.Inject | import javax.inject.Inject | ||||||
| 
 | 
 | ||||||
| @HiltViewModel | @HiltViewModel | ||||||
| class NavigationBarViewModel @Inject constructor( | class NavigationBarViewModel @Inject constructor( | ||||||
|     private val accountDAO: AccountDAO, |  | ||||||
|     logService: LogService |     logService: LogService | ||||||
| ) : StudeezViewModel(logService) { | ) : StudeezViewModel(logService) { | ||||||
| 
 | 
 | ||||||
|  | @ -19,7 +18,7 @@ class NavigationBarViewModel @Inject constructor( | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun onTasksClick(open: (String) -> Unit) { |     fun onTasksClick(open: (String) -> Unit) { | ||||||
|         // TODO |         open(TASKS_SCREEN) | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     fun onSessionsClick(open: (String) -> Unit) { |     fun onSessionsClick(open: (String) -> Unit) { | ||||||
|  |  | ||||||
|  | @ -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 | @Module | ||||||
| @InstallIn(SingletonComponent::class) | @InstallIn(SingletonComponent::class) | ||||||
| abstract class DatabaseModule { | 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 | package be.ugent.sel.studeez.domain.implementation | ||||||
| 
 | 
 | ||||||
| object FirebaseCollectionRoutes { | object FireBaseCollections { | ||||||
|     const val SESSION_COLLECTION = "sessions" |     const val SESSION_COLLECTION = "sessions" | ||||||
|     const val USER_COLLECTION = "users" |     const val USER_COLLECTION = "users" | ||||||
|     const val TIMER_COLLECTION = "timers" |     const val TIMER_COLLECTION = "timers" | ||||||
| 
 |     const val SUBJECT_COLLECTION = "subjects" | ||||||
| } | } | ||||||
|  | @ -31,8 +31,7 @@ class FireBaseSessionDAO @Inject constructor( | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun currentUserSessionsCollection(): CollectionReference = |     private fun currentUserSessionsCollection(): CollectionReference = | ||||||
|         firestore.collection(FirebaseCollectionRoutes.USER_COLLECTION) |         firestore.collection(FireBaseCollections.USER_COLLECTION) | ||||||
|             .document(auth.currentUserId) |             .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 | 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.* | ||||||
| import be.ugent.sel.studeez.data.local.models.timer_info.TimerType.* |  | ||||||
| import be.ugent.sel.studeez.domain.AccountDAO | import be.ugent.sel.studeez.domain.AccountDAO | ||||||
| import be.ugent.sel.studeez.domain.TimerDAO | import be.ugent.sel.studeez.domain.TimerDAO | ||||||
| import com.google.firebase.firestore.CollectionReference | import com.google.firebase.firestore.CollectionReference | ||||||
| import com.google.firebase.firestore.DocumentSnapshot |  | ||||||
| import com.google.firebase.firestore.FirebaseFirestore | import com.google.firebase.firestore.FirebaseFirestore | ||||||
| import com.google.firebase.firestore.ktx.snapshots | import com.google.firebase.firestore.ktx.snapshots | ||||||
| import kotlinx.coroutines.flow.Flow | import kotlinx.coroutines.flow.Flow | ||||||
|  | @ -50,8 +48,8 @@ class FirebaseTimerDAO @Inject constructor( | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private fun currentUserTimersCollection(): CollectionReference = |     private fun currentUserTimersCollection(): CollectionReference = | ||||||
|         firestore.collection(FirebaseCollectionRoutes.USER_COLLECTION) |         firestore.collection(FireBaseCollections.USER_COLLECTION) | ||||||
|             .document(auth.currentUserId) |             .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 TIMER_SELECTION_SCREEN = "timer_selection" | ||||||
|     const val SESSION_SCREEN = "session" |     const val SESSION_SCREEN = "session" | ||||||
|     const val SESSION_RECAP = "session_recap" |     const val SESSION_RECAP = "session_recap" | ||||||
|  //    const val TASKS_SCREEN = "tasks" |      const val TASKS_SCREEN = "tasks" | ||||||
|  //    const val SESSIONS_SCREEN = "sessions" |  //    const val SESSIONS_SCREEN = "sessions" | ||||||
|     const val PROFILE_SCREEN = "profile" |     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