diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..603b140
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,14 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
diff --git a/.idea/codeStyles/Project.xml b/.idea/codeStyles/Project.xml
new file mode 100644
index 0000000..88ea3aa
--- /dev/null
+++ b/.idea/codeStyles/Project.xml
@@ -0,0 +1,122 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ xmlns:android
+
+ ^$
+
+
+
+
+
+
+
+
+ xmlns:.*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*:id
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ .*:name
+
+ http://schemas.android.com/apk/res/android
+
+
+
+
+
+
+
+
+ name
+
+ ^$
+
+
+
+
+
+
+
+
+ style
+
+ ^$
+
+
+
+
+
+
+
+
+ .*
+
+ ^$
+
+
+ BY_NAME
+
+
+
+
+
+
+ .*
+
+ http://schemas.android.com/apk/res/android
+
+
+ ANDROID_ATTRIBUTE_ORDER
+
+
+
+
+
+
+ .*
+
+ .*
+
+
+ BY_NAME
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/codeStyles/codeStyleConfig.xml b/.idea/codeStyles/codeStyleConfig.xml
new file mode 100644
index 0000000..79ee123
--- /dev/null
+++ b/.idea/codeStyles/codeStyleConfig.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/gradle.xml b/.idea/gradle.xml
new file mode 100644
index 0000000..5cd135a
--- /dev/null
+++ b/.idea/gradle.xml
@@ -0,0 +1,20 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/misc.xml b/.idea/misc.xml
new file mode 100644
index 0000000..37a7509
--- /dev/null
+++ b/.idea/misc.xml
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml
new file mode 100644
index 0000000..7f68460
--- /dev/null
+++ b/.idea/runConfigurations.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/.gitignore b/app/.gitignore
new file mode 100644
index 0000000..796b96d
--- /dev/null
+++ b/app/.gitignore
@@ -0,0 +1 @@
+/build
diff --git a/app/build.gradle b/app/build.gradle
new file mode 100644
index 0000000..2874e5c
--- /dev/null
+++ b/app/build.gradle
@@ -0,0 +1,67 @@
+apply plugin: 'com.android.application'
+apply plugin: 'kotlin-android'
+apply plugin: 'kotlin-android-extensions'
+apply plugin: 'kotlin-kapt'
+apply plugin: 'androidx.navigation.safeargs'
+
+android {
+ compileSdkVersion 29
+ buildToolsVersion "29.0.3"
+
+ defaultConfig {
+ applicationId "com.taymath.tutortoolkit"
+ minSdkVersion 19
+ targetSdkVersion 29
+ versionCode 1
+ versionName "1.0"
+ vectorDrawables.useSupportLibrary = true
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+
+ // Enables data binding.
+ dataBinding {
+ enabled = true
+ }
+
+}
+
+dependencies {
+ implementation fileTree(dir: 'libs', include: ['*.jar'])
+ implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$version_kotlin"
+
+
+ implementation 'androidx.appcompat:appcompat:1.1.0'
+ implementation 'androidx.core:core-ktx:1.2.0'
+ implementation 'androidx.constraintlayout:constraintlayout:1.1.3'
+
+ // Support libraries
+ implementation "androidx.appcompat:appcompat:$version_appcompat"
+ implementation "androidx.fragment:fragment:$version_fragment"
+ implementation "androidx.constraintlayout:constraintlayout:$version_constraint_layout"
+
+ // Room and Lifecycle dependencies
+ implementation "androidx.room:room-runtime:$version_room"
+ kapt "androidx.room:room-compiler:$version_room"
+ implementation "androidx.lifecycle:lifecycle-extensions:$version_lifecycle_extensions"
+
+ // Navigation
+ implementation 'androidx.navigation:navigation-fragment-ktx:2.2.1'
+ implementation 'androidx.navigation:navigation-ui-ktx:2.2.1'
+
+ // Coroutines
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-core:$version_coroutine"
+ implementation "org.jetbrains.kotlinx:kotlinx-coroutines-android:$version_coroutine"
+
+ // Testing
+ testImplementation 'junit:junit:4.12'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.0'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.1.1'
+}
diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro
new file mode 100644
index 0000000..f1b4245
--- /dev/null
+++ b/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
diff --git a/app/src/androidTest/java/com/taymath/tutortoolkit/ExampleInstrumentedTest.kt b/app/src/androidTest/java/com/taymath/tutortoolkit/ExampleInstrumentedTest.kt
new file mode 100644
index 0000000..4542276
--- /dev/null
+++ b/app/src/androidTest/java/com/taymath/tutortoolkit/ExampleInstrumentedTest.kt
@@ -0,0 +1,24 @@
+package com.taymath.tutortoolkit
+
+import androidx.test.platform.app.InstrumentationRegistry
+import androidx.test.ext.junit.runners.AndroidJUnit4
+
+import org.junit.Test
+import org.junit.runner.RunWith
+
+import org.junit.Assert.*
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+@RunWith(AndroidJUnit4::class)
+class ExampleInstrumentedTest {
+ @Test
+ fun useAppContext() {
+ // Context of the app under test.
+ val appContext = InstrumentationRegistry.getInstrumentation().targetContext
+ assertEquals("com.taymath.tutortoolkit", appContext.packageName)
+ }
+}
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
new file mode 100644
index 0000000..e000ff3
--- /dev/null
+++ b/app/src/main/AndroidManifest.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/ic_launcher-playstore.png b/app/src/main/ic_launcher-playstore.png
new file mode 100644
index 0000000..7817754
Binary files /dev/null and b/app/src/main/ic_launcher-playstore.png differ
diff --git a/app/src/main/java/com/taymath/tutortoolkit/MainActivity.kt b/app/src/main/java/com/taymath/tutortoolkit/MainActivity.kt
new file mode 100644
index 0000000..1d463f7
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/MainActivity.kt
@@ -0,0 +1,17 @@
+package com.taymath.tutortoolkit
+
+import androidx.appcompat.app.AppCompatActivity
+import android.os.Bundle
+
+/**
+ * This main activity is just a container for our fragments,
+ * where the real action is.
+ */
+class MainActivity : AppCompatActivity() {
+
+ override fun onCreate(savedInstanceState: Bundle?) {
+ super.onCreate(savedInstanceState)
+
+ setContentView(R.layout.activity_main)
+ }
+}
diff --git a/app/src/main/java/com/taymath/tutortoolkit/addgrade/AddGradeFragment.kt b/app/src/main/java/com/taymath/tutortoolkit/addgrade/AddGradeFragment.kt
new file mode 100644
index 0000000..c972d82
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/addgrade/AddGradeFragment.kt
@@ -0,0 +1,68 @@
+package com.taymath.tutortoolkit.addgrade
+
+import android.os.Bundle
+import android.text.Editable
+import android.text.TextWatcher
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import android.widget.EditText
+import androidx.databinding.DataBindingUtil
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProviders
+import androidx.navigation.fragment.findNavController
+import com.taymath.tutortoolkit.R
+import com.taymath.tutortoolkit.addstudent.AddStudentFragmentDirections
+import com.taymath.tutortoolkit.databinding.FragmentAddGradeBindingImpl
+import com.taymath.tutortoolkit.databinding.FragmentAddStudentBindingImpl
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabase
+import kotlinx.android.synthetic.main.fragment_add_grade.*
+
+class AddGradeFragment : Fragment() {
+
+ /**
+ * Called when the Fragment is ready to display content to the screen.
+ *
+ * This function uses DataBindingUtil to inflate R.layout.fragment_add_grade.
+ */
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+
+ // Get a reference to the binding object and inflate the fragment views.
+ val binding: FragmentAddGradeBindingImpl = DataBindingUtil.inflate(
+ inflater, R.layout.fragment_add_grade, container, false)
+
+ // Get reference to application
+ val application = requireNotNull(this.activity).application
+
+ // Get a reference to the DAO
+ val dataSource = StudentDatabase.getInstance(application).studentDatabaseDao
+
+ // Grab our arguments from previous fragment
+ val arguments = AddGradeFragmentArgs.fromBundle(arguments!!)
+
+ // Create instance of viewModelFactory using DAO and application
+ val viewModelFactory = AddGradeViewModelFactory(arguments.studentId, dataSource)
+
+ // Get reference to viewModel
+ val addGradeViewModel =
+ ViewModelProviders.of(
+ this, viewModelFactory).get(AddGradeViewModel::class.java)
+
+ // Add view model to our binding
+ binding.addGradeViewModel = addGradeViewModel
+
+ binding.setLifecycleOwner(this)
+
+ // Listen for when we navigate to student list
+ addGradeViewModel.navigateToStudentList.observe(viewLifecycleOwner, Observer {
+ if (it == true) { // Observed state is true.
+ this.findNavController().navigate(
+ AddGradeFragmentDirections.actionAddGradeFragmentToStudentListFragment())
+ addGradeViewModel.doneNavigating()
+ }
+ })
+ return binding.root
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/taymath/tutortoolkit/addgrade/AddGradeViewModel.kt b/app/src/main/java/com/taymath/tutortoolkit/addgrade/AddGradeViewModel.kt
new file mode 100644
index 0000000..07c3857
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/addgrade/AddGradeViewModel.kt
@@ -0,0 +1,79 @@
+package com.taymath.tutortoolkit.addgrade
+
+import android.content.Context
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MediatorLiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.taymath.tutortoolkit.studentdatabase.Grade
+import com.taymath.tutortoolkit.studentdatabase.Student
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabaseDao
+import kotlinx.coroutines.*
+
+class AddGradeViewModel(
+ var student_id: Long,
+ val database: StudentDatabaseDao
+) : ViewModel() {
+
+ // Initialize viewModelJob
+ private val viewModelJob = Job()
+
+ // Initialize uiScope
+ private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
+
+ // Setup Livdata to signal when to navigate to studentList
+ private val _navigateToStudentList = MutableLiveData()
+ val navigateToStudentList: LiveData
+ get() = _navigateToStudentList
+
+ val gradeFloatText = MutableLiveData()
+
+ // Initialize mediatorLiveData containing Student Class
+ private val student = MediatorLiveData()
+
+ fun getStudent() = student
+
+ // Add Student from database to our mediatorLiveData
+ init {
+ student.addSource(database.getStudentWithId(student_id), student::setValue)
+ }
+
+// fun validateForm(): Boolean {
+// return gradeFloatText.value!!.isNotEmpty()
+// }
+
+
+ // Initialize Grade and add to grade_table
+ fun onAddGrade(
+ gradeString: String,
+ gradeFloat: Float,
+ noteString: String,
+ studentNameString: String
+ ) {
+ uiScope.launch {
+ withContext(Dispatchers.IO) {
+ val newGrade = Grade()
+ newGrade.studentNameString = studentNameString
+ newGrade.gradeString = gradeString
+ newGrade.gradeFloat = gradeFloat
+ newGrade.noteString = noteString
+ newGrade.studentIdLong = student_id
+ insert(newGrade)
+ }
+ }
+ _navigateToStudentList.value = true
+ }
+
+ override fun onCleared() {
+ super.onCleared()
+ viewModelJob.cancel()
+ }
+
+ fun doneNavigating() {
+ _navigateToStudentList.value = false
+ }
+
+ private fun insert(grade: Grade) {
+ database.insertGrade(grade)
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/taymath/tutortoolkit/addgrade/AddGradeViewModelFactory.kt b/app/src/main/java/com/taymath/tutortoolkit/addgrade/AddGradeViewModelFactory.kt
new file mode 100644
index 0000000..8f786dd
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/addgrade/AddGradeViewModelFactory.kt
@@ -0,0 +1,20 @@
+package com.taymath.tutortoolkit.addgrade
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.taymath.tutortoolkit.studentdatabase.Student
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabaseDao
+
+class AddGradeViewModelFactory(
+ private val student_id: Long,
+ private val dataSource: StudentDatabaseDao
+) : ViewModelProvider.Factory {
+
+ @Suppress("unchecked_cast")
+ override fun create(modelClass: Class): T {
+ if (modelClass.isAssignableFrom(AddGradeViewModel::class.java)) {
+ return AddGradeViewModel(student_id, dataSource) as T
+ }
+ throw IllegalArgumentException("Unknown ViewModel class")
+ }
+}
diff --git a/app/src/main/java/com/taymath/tutortoolkit/addstudent/AddStudentFragment.kt b/app/src/main/java/com/taymath/tutortoolkit/addstudent/AddStudentFragment.kt
new file mode 100644
index 0000000..3532589
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/addstudent/AddStudentFragment.kt
@@ -0,0 +1,59 @@
+package com.taymath.tutortoolkit.addstudent
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.databinding.DataBindingUtil
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProviders
+import androidx.navigation.fragment.findNavController
+import com.taymath.tutortoolkit.R
+import com.taymath.tutortoolkit.databinding.FragmentAddStudentBindingImpl
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabase
+
+class AddStudentFragment : Fragment() {
+
+ /**
+ * Called when the Fragment is ready to display content to the screen.
+ *
+ * This function uses DataBindingUtil to inflate R.layout.fragment_add_student.
+ */
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+
+ // Get a reference to the binding object and inflate the fragment views.
+ val binding: FragmentAddStudentBindingImpl = DataBindingUtil.inflate(
+ inflater, R.layout.fragment_add_student, container, false)
+
+ // Get reference to application
+ val application = requireNotNull(this.activity).application
+
+ // Get a reference to the DAO
+ val dataSource = StudentDatabase.getInstance(application).studentDatabaseDao
+
+ // Create instance of viewModelFactory using DAO and application
+ val viewModelFactory = AddStudentViewModelFactory(dataSource)
+
+ // Get reference to viewModel
+ val addStudentViewModel =
+ ViewModelProviders.of(
+ this, viewModelFactory).get(AddStudentViewModel::class.java)
+
+ // Add our viewModel to binding
+ binding.addStudentViewModel = addStudentViewModel
+
+ binding.setLifecycleOwner(this)
+
+ // Listen for when we navigate to student list
+ addStudentViewModel.navigateToStudentList.observe(viewLifecycleOwner, Observer {
+ if (it == true) { // Observed state is true.
+ this.findNavController().navigate(
+ AddStudentFragmentDirections.actionAddStudentFragmentToStudentListFragment())
+ addStudentViewModel.doneNavigating()
+ }
+ })
+ return binding.root
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/taymath/tutortoolkit/addstudent/AddStudentViewModel.kt b/app/src/main/java/com/taymath/tutortoolkit/addstudent/AddStudentViewModel.kt
new file mode 100644
index 0000000..bc40714
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/addstudent/AddStudentViewModel.kt
@@ -0,0 +1,67 @@
+package com.taymath.tutortoolkit.addstudent
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.taymath.tutortoolkit.studentdatabase.Student
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabaseDao
+import kotlinx.coroutines.*
+
+class AddStudentViewModel(
+ val database: StudentDatabaseDao
+) : ViewModel() {
+
+ // Initialize viewModelJob
+ private val viewModelJob = Job()
+
+ // Initialize uiScope
+ private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
+
+ // Setup Livdata to signal when to navigate to studentList
+ private val _navigateToStudentList = MutableLiveData()
+ val navigateToStudentList: LiveData
+ get() = _navigateToStudentList
+
+ // Initialize Student and add to student_table
+ fun onAddStudent(studentNameString : String, subjectString: String,
+ gradeLevelString: String, addressString: String, emailString: String) {
+ uiScope.launch {
+ withContext(Dispatchers.IO) {
+ val newStudent = Student()
+ newStudent.studentNameString = studentNameString
+ newStudent.subjectString = subjectString
+ newStudent.emailString = emailString
+ newStudent.gradeLevelString = gradeLevelString
+ newStudent.addressString = addressString
+ insert(newStudent)
+ }
+ }
+ _navigateToStudentList.value = true
+ }
+
+ override fun onCleared() {
+ super.onCleared()
+ viewModelJob.cancel()
+ }
+
+ fun doneNavigating() {
+ _navigateToStudentList.value = null
+ }
+
+ private suspend fun insert(student: Student) {
+ withContext(Dispatchers.IO) {
+ database.insertStudent(student)
+ }
+ }
+
+// fun onSetSleepQuality(quality: Int) {
+// uiScope.launch {
+// withContext(Dispatchers.IO) {
+// val tonight = database.get(sleepNightKey) ?: return@withContext
+// tonight.sleepQuality = quality
+// database.update(tonight)
+// }
+// _navigateToSleepTracker.value = true
+// }
+// }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/taymath/tutortoolkit/addstudent/AddStudentViewModelFactory.kt b/app/src/main/java/com/taymath/tutortoolkit/addstudent/AddStudentViewModelFactory.kt
new file mode 100644
index 0000000..58c5206
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/addstudent/AddStudentViewModelFactory.kt
@@ -0,0 +1,18 @@
+package com.taymath.tutortoolkit.addstudent
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabaseDao
+
+class AddStudentViewModelFactory(
+ private val dataSource: StudentDatabaseDao
+) : ViewModelProvider.Factory {
+
+ @Suppress("unchecked_cast")
+ override fun create(modelClass: Class): T {
+ if (modelClass.isAssignableFrom(AddStudentViewModel::class.java)) {
+ return AddStudentViewModel(dataSource) as T
+ }
+ throw IllegalArgumentException("Unknown ViewModel class")
+ }
+}
diff --git a/app/src/main/java/com/taymath/tutortoolkit/chooseicon/ChooseIconFragment.kt b/app/src/main/java/com/taymath/tutortoolkit/chooseicon/ChooseIconFragment.kt
new file mode 100644
index 0000000..f192317
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/chooseicon/ChooseIconFragment.kt
@@ -0,0 +1,59 @@
+package com.taymath.tutortoolkit.chooseicon
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.databinding.DataBindingUtil
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.ViewModelProviders
+import androidx.navigation.fragment.findNavController
+import com.taymath.tutortoolkit.R
+import com.taymath.tutortoolkit.databinding.FragmentChooseIconBinding
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabase
+
+class ChooseIconFragment : Fragment() {
+
+ /**
+ * Called when the Fragment is ready to display content to the screen.
+ *
+ * This function uses DataBindingUtil to inflate R.layout.fragment_sleep_quality.
+ */
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+
+ // Get a reference to the binding object and inflate the fragment views.
+ val binding: FragmentChooseIconBinding = DataBindingUtil.inflate(
+ inflater, R.layout.fragment_choose_icon, container, false)
+
+ val application = requireNotNull(this.activity).application
+
+// val arguments = SleepQualityFragmentArgs.fromBundle(arguments!!)
+
+ // Create an instance of the ViewModel Factory.
+ val dataSource = StudentDatabase.getInstance(application).studentDatabaseDao
+ val viewModelFactory = ChooseIconViewModelFactory(dataSource)
+
+ // Get a reference to the ViewModel associated with this fragment.
+ val chooseIconViewModel =
+ ViewModelProviders.of(
+ this, viewModelFactory).get(ChooseIconViewModel::class.java)
+
+ // To use the View Model with data binding, you have to explicitly
+ // give the binding object a reference to it.
+ binding.chooseIconViewModel = chooseIconViewModel
+
+ // Add an Observer to the state variable for Navigating when a Quality icon is tapped.
+// chooseIconViewModel.navigateToSleepTracker.observe(this, Observer {
+// if (it == true) { // Observed state is true.
+// this.findNavController().navigate(
+// SleepQualityFragmentDirections.actionSleepQualityFragmentToSleepTrackerFragment())
+// // Reset state to make sure we only navigate once, even if the device
+// // has a configuration change.
+// sleepQualityViewModel.doneNavigating()
+// }
+// })
+
+ return binding.root
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/taymath/tutortoolkit/chooseicon/ChooseIconViewModel.kt b/app/src/main/java/com/taymath/tutortoolkit/chooseicon/ChooseIconViewModel.kt
new file mode 100644
index 0000000..83404eb
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/chooseicon/ChooseIconViewModel.kt
@@ -0,0 +1,81 @@
+package com.taymath.tutortoolkit.chooseicon
+
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import androidx.lifecycle.ViewModel
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabaseDao
+import kotlinx.coroutines.*
+
+class ChooseIconViewModel(
+ val database: StudentDatabaseDao) : ViewModel() {
+
+ /** Coroutine setup variables */
+
+ /**
+ * viewModelJob allows us to cancel all coroutines started by this ViewModel.
+ */
+ private val viewModelJob = Job()
+
+ /**
+ * A [CoroutineScope] keeps track of all coroutines started by this ViewModel.
+ *
+ * Because we pass it [viewModelJob], any coroutine started in this scope can be cancelled
+ * by calling `viewModelJob.cancel()`
+ *
+ * By default, all coroutines started in uiScope will launch in [Dispatchers.Main] which is
+ * the main thread on Android. This is a sensible default because most coroutines started by
+ * a [ViewModel] update the UI after performing some processing.
+ */
+ private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
+
+ /**
+ * Variable that tells the fragment whether it should navigate to [SleepTrackerFragment].
+ *
+ * This is `private` because we don't want to expose the ability to set [MutableLiveData] to
+ * the [Fragment]
+ */
+ private val _navigateToSleepTracker = MutableLiveData()
+
+ /**
+ * When true immediately navigate back to the [SleepTrackerFragment]
+ */
+ val navigateToSleepTracker: LiveData
+ get() = _navigateToSleepTracker
+
+ /**
+ * Cancels all coroutines when the ViewModel is cleared, to cleanup any pending work.
+ *
+ * onCleared() gets called when the ViewModel is destroyed.
+ */
+ override fun onCleared() {
+ super.onCleared()
+ viewModelJob.cancel()
+ }
+
+ /**
+ * Call this immediately after navigating to [SleepTrackerFragment]
+ */
+ fun doneNavigating() {
+ _navigateToSleepTracker.value = null
+ }
+
+ /**
+ * Sets the sleep quality and updates the database.
+ *
+ * Then navigates back to the SleepTrackerFragment.
+ */
+// fun onSetSleepQuality(quality: Int) {
+// uiScope.launch {
+// // IO is a thread pool for running operations that access the disk, such as
+// // our Room database.
+// withContext(Dispatchers.IO) {
+// val tonight = database.get(sleepNightKey) ?: return@withContext
+// tonight.sleepQuality = quality
+// database.update(tonight)
+// }
+//
+// // Setting this state variable to true will alert the observer and trigger navigation.
+// _navigateToSleepTracker.value = true
+// }
+// }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/taymath/tutortoolkit/chooseicon/ChooseIconViewModelFactory.kt b/app/src/main/java/com/taymath/tutortoolkit/chooseicon/ChooseIconViewModelFactory.kt
new file mode 100644
index 0000000..cffed31
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/chooseicon/ChooseIconViewModelFactory.kt
@@ -0,0 +1,16 @@
+package com.taymath.tutortoolkit.chooseicon
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabaseDao
+
+class ChooseIconViewModelFactory(
+ private val dataSource: StudentDatabaseDao) : ViewModelProvider.Factory {
+ @Suppress("unchecked_cast")
+ override fun create(modelClass: Class): T {
+ if (modelClass.isAssignableFrom(ChooseIconViewModel::class.java)) {
+ return ChooseIconViewModel(dataSource) as T
+ }
+ throw IllegalArgumentException("Unknown ViewModel class")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/taymath/tutortoolkit/studentdatabase/Grade.kt b/app/src/main/java/com/taymath/tutortoolkit/studentdatabase/Grade.kt
new file mode 100644
index 0000000..4f81180
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/studentdatabase/Grade.kt
@@ -0,0 +1,30 @@
+package com.taymath.tutortoolkit.studentdatabase
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "grade_table")
+data class Grade (
+
+ @PrimaryKey(autoGenerate = true)
+ var gradeId: Long = 0L,
+
+ @ColumnInfo(name="grade_string")
+ var gradeString: String = "BLANK Grade",
+
+ @ColumnInfo(name = "student_name_string")
+ var studentNameString: String = "CHECK_GRADE.KT",
+
+ @ColumnInfo(name = "grade_float")
+ var gradeFloat: Float = 0F,
+
+ @ColumnInfo(name = "time_milli")
+ val startTimeMilli: Long = System.currentTimeMillis(),
+
+ @ColumnInfo(name = "note_string")
+ var noteString: String = "CHECK_GRADE.KT",
+
+ @ColumnInfo(name= "student_id_long")
+ var studentIdLong: Long = 0L
+)
\ No newline at end of file
diff --git a/app/src/main/java/com/taymath/tutortoolkit/studentdatabase/Student.kt b/app/src/main/java/com/taymath/tutortoolkit/studentdatabase/Student.kt
new file mode 100644
index 0000000..ff390c5
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/studentdatabase/Student.kt
@@ -0,0 +1,47 @@
+/*
+ * Copyright 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.taymath.tutortoolkit.studentdatabase
+
+import androidx.room.ColumnInfo
+import androidx.room.Entity
+import androidx.room.PrimaryKey
+
+@Entity(tableName = "student_table")
+data class Student (
+
+ @PrimaryKey(autoGenerate = true)
+ var studentId: Long = 0L,
+
+ @ColumnInfo(name="student_name")
+ var studentNameString: String = "BLANK STUDENT",
+
+ @ColumnInfo(name = "todo_string")
+ var todoString: String = "CHECK_Student.KT",
+
+ @ColumnInfo(name = "subject")
+ var subjectString: String = "CHECK_Student.KT",
+
+ @ColumnInfo(name = "grade_level")
+ var gradeLevelString: String = "CHECK_Student.KT",
+
+ @ColumnInfo(name = "address")
+ var addressString: String = "CHECK_Student.KT",
+
+ @ColumnInfo(name = "email")
+ var emailString: String = "CHECK_Student.KT"
+
+)
diff --git a/app/src/main/java/com/taymath/tutortoolkit/studentdatabase/StudentDatabase.kt b/app/src/main/java/com/taymath/tutortoolkit/studentdatabase/StudentDatabase.kt
new file mode 100644
index 0000000..a97f608
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/studentdatabase/StudentDatabase.kt
@@ -0,0 +1,49 @@
+/*
+ * Copyright 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.taymath.tutortoolkit.studentdatabase
+
+import android.content.Context
+import androidx.room.Database
+import androidx.room.Room
+import androidx.room.RoomDatabase
+
+@Database(entities = [Student::class, Grade::class], version = 1, exportSchema = false)
+abstract class StudentDatabase : RoomDatabase() {
+
+ abstract val studentDatabaseDao: StudentDatabaseDao
+
+ companion object {
+ @Volatile
+ private var INSTANCE: StudentDatabase? = null
+
+ fun getInstance(context: Context): StudentDatabase {
+ synchronized(this) {
+ var instance = INSTANCE
+
+ if (instance == null) {
+ instance = Room.databaseBuilder(
+ context.applicationContext,
+ StudentDatabase::class.java,
+ "student_database"
+ ).fallbackToDestructiveMigration().build()
+ }
+
+ return instance
+ }
+ }
+ }
+}
diff --git a/app/src/main/java/com/taymath/tutortoolkit/studentdatabase/StudentDatabaseDao.kt b/app/src/main/java/com/taymath/tutortoolkit/studentdatabase/StudentDatabaseDao.kt
new file mode 100644
index 0000000..e191532
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/studentdatabase/StudentDatabaseDao.kt
@@ -0,0 +1,87 @@
+/*
+ * Copyright 2018, The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package com.taymath.tutortoolkit.studentdatabase
+
+import androidx.lifecycle.LiveData
+import androidx.room.Dao
+import androidx.room.Insert
+import androidx.room.Query
+import androidx.room.Update
+
+@Dao
+interface StudentDatabaseDao {
+
+ // Student Table Dao
+ @Insert
+ fun insertStudent(student: Student)
+
+ @Update
+ fun updateStudent(student: Student)
+
+ @Query("DELETE FROM student_table WHERE studentId = :studentId")
+ fun deleteStudent(studentId: Long)
+
+ @Query("DELETE FROM student_table")
+ fun clearStudentTable()
+
+ @Query("SELECT * FROM student_table ORDER BY studentId DESC LIMIT 1")
+ fun getStudent(): Student?
+
+ @Query("SELECT * FROM student_table ORDER BY studentId DESC")
+ fun getAllStudents(): LiveData>
+
+ @Query("SELECT * from student_table WHERE studentId = :key")
+ fun getStudentWithId(key: Long): LiveData
+
+ @Query("SELECT * FROM student_table WHERE studentId = :studentId")
+ fun getStudentClassWithId(studentId: Long): Student
+
+ @Query("SELECT * from student_table WHERE student_name = :studentName")
+ fun getStudentWithName(studentName: String): LiveData
+
+
+
+ // Grade Table Dao
+ @Insert
+ fun insertGrade(grade: Grade)
+
+ @Update
+ fun updateGrade(grade: Grade)
+
+ @Query("DELETE FROM grade_table WHERE student_id_long = :studentId")
+ fun deleteGradeTable(studentId: Long)
+
+ @Query("DELETE FROM grade_table")
+ fun clearGradeTable()
+
+ @Query("SELECT * FROM grade_table ORDER BY gradeId DESC LIMIT 1")
+ fun getGrade(): Grade?
+
+ @Query("SELECT * FROM grade_table ORDER BY student_name_string DESC")
+ fun getAllGrades(): LiveData>
+
+ @Query("SELECT * FROM grade_table WHERE student_name_string = :studentName")
+ fun getGradesForStudent(studentName: String): LiveData>
+
+ @Query("SELECT * from grade_table WHERE gradeId = :key")
+ fun getGradeWithId(key: Long): LiveData
+
+ @Query("SELECT * from grade_table WHERE student_id_long = :studentId")
+ fun getGradesWithStudentId(studentId: Long): LiveData>
+
+}
+
diff --git a/app/src/main/java/com/taymath/tutortoolkit/studentdetail/GradeAdapter.kt b/app/src/main/java/com/taymath/tutortoolkit/studentdetail/GradeAdapter.kt
new file mode 100644
index 0000000..ba0f8cb
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/studentdetail/GradeAdapter.kt
@@ -0,0 +1,66 @@
+package com.taymath.tutortoolkit.studentdetail
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import com.taymath.tutortoolkit.databinding.ListItemGradeBinding
+import com.taymath.tutortoolkit.studentdatabase.Grade
+
+class GradeAdapter : ListAdapter(GradeDiffCallback()) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ return ViewHolder.from(parent)
+ }
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(getItem(position))
+ }
+
+ class ViewHolder private constructor(val binding: ListItemGradeBinding)
+ : RecyclerView.ViewHolder(binding.root) {
+
+ fun bind(item: Grade) {
+ binding.grade = item
+ binding.executePendingBindings()
+ }
+
+ companion object {
+ fun from(parent: ViewGroup): ViewHolder {
+ val layoutInflater = LayoutInflater.from(parent.context)
+ val binding = ListItemGradeBinding.inflate(layoutInflater, parent, false)
+ return ViewHolder(binding)
+ }
+ }
+ }
+
+ class GradeDiffCallback : DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(oldItem: Grade, newItem: Grade): Boolean {
+ return oldItem.gradeId == newItem.gradeId
+ }
+
+ override fun areContentsTheSame(oldItem: Grade, newItem: Grade): Boolean {
+ return oldItem == newItem
+ }
+ }
+}
+
+/**
+ * Callback for calculating the diff between two non-null items in a list.
+ *
+ * Used by ListAdapter to calculate the minumum number of changes between and old list and a new
+ * list that's been passed to `submitList`.
+ */
+
+
+class GradeDiffCallback : DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(oldItem: Grade, newItem: Grade): Boolean {
+ return oldItem.gradeId == newItem.gradeId
+ }
+
+ override fun areContentsTheSame(oldItem: Grade, newItem: Grade): Boolean {
+ return oldItem == newItem
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/taymath/tutortoolkit/studentdetail/GradeBindingUtils.kt b/app/src/main/java/com/taymath/tutortoolkit/studentdetail/GradeBindingUtils.kt
new file mode 100644
index 0000000..4b4a9f4
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/studentdetail/GradeBindingUtils.kt
@@ -0,0 +1,26 @@
+package com.taymath.tutortoolkit.studentdetail
+
+import android.widget.TextView
+import androidx.databinding.BindingAdapter
+import com.taymath.tutortoolkit.studentdatabase.Grade
+
+@BindingAdapter("gradeFloat")
+fun TextView.setGradeFloat(item: Grade?){
+ item?.let {
+ text = item.gradeFloat.toString()
+ }
+}
+
+@BindingAdapter("gradeString")
+fun TextView.setSubjectText(item: Grade?){
+ item?.let {
+ text =item.gradeString
+ }
+}
+
+@BindingAdapter("noteString")
+fun TextView.setStudentNameText(item: Grade?){
+ item?.let {
+ text =item.noteString
+ }
+}
diff --git a/app/src/main/java/com/taymath/tutortoolkit/studentdetail/StudentDetailFragment.kt b/app/src/main/java/com/taymath/tutortoolkit/studentdetail/StudentDetailFragment.kt
new file mode 100644
index 0000000..9de61f2
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/studentdetail/StudentDetailFragment.kt
@@ -0,0 +1,79 @@
+package com.taymath.tutortoolkit.studentdetail
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.databinding.DataBindingUtil
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProviders
+import androidx.navigation.fragment.findNavController
+import com.taymath.tutortoolkit.R
+import com.taymath.tutortoolkit.databinding.FragmentStudentDetailBinding
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabase
+import com.taymath.tutortoolkit.studentlist.StudentListFragmentDirections
+import com.taymath.tutortoolkit.studentlist.StudentListener
+
+class StudentDetailFragment: Fragment() {
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+
+ val binding:FragmentStudentDetailBinding = DataBindingUtil.inflate(
+ inflater, R.layout.fragment_student_detail, container,false
+ )
+
+ val application = requireNotNull(this.activity).application
+ val arguments = StudentDetailFragmentArgs.fromBundle(arguments!!)
+
+ // Create an instance of the ViewModel Factory.
+ val dataSource = StudentDatabase.getInstance(application).studentDatabaseDao
+ val viewModelFactory = StudentDetailViewModelFactory(dataSource, arguments.studentId)
+
+ // Get a reference to the ViewModel associated with this fragment.
+ val studentDetailViewModel =
+ ViewModelProviders.of(
+ this, viewModelFactory).get(StudentDetailViewModel::class.java)
+
+ // To use the View Model with data binding, you have to explicitly
+ // give the binding object a reference to it.
+ binding.studentDetailViewModel = studentDetailViewModel
+
+ binding.setLifecycleOwner(this)
+
+ // Add an Observer to the state variable for Navigating when Add Grade button is clicked.
+ studentDetailViewModel.navigateToAddGrade.observe(viewLifecycleOwner, Observer {
+ if (it == true) { // Observed state is true.
+ this.findNavController().navigate(
+ StudentDetailFragmentDirections.actionStudentDetailFragmentToAddGradeFragment(arguments.studentId))
+ // Reset state to make sure we only navigate once, even if the device
+ // has a configuration change.
+ studentDetailViewModel.doneNavigating()
+ }
+ })
+
+ // Add an Observer to the state variable for Navigating when Add Grade button is clicked.
+ studentDetailViewModel.navigateToStudentList.observe(viewLifecycleOwner, Observer {
+ if (it == true) { // Observed state is true.
+ this.findNavController().navigate(
+ StudentDetailFragmentDirections.actionStudentDetailFragmentToStudentListFragment())
+ // Reset state to make sure we only navigate once, even if the device
+ // has a configuration change.
+ studentDetailViewModel.doneNavigating()
+ }
+ })
+
+ // Initialize adapter and add to gradeList
+ val adapter = GradeAdapter()
+ binding.gradeList.adapter = adapter
+
+ // If we have a list of grades, send it to the adapter
+ studentDetailViewModel.grades.observe(viewLifecycleOwner, Observer {
+ it?.let {
+ adapter.submitList(it)
+ }
+ })
+
+ return binding.root
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/taymath/tutortoolkit/studentdetail/StudentDetailViewModel.kt b/app/src/main/java/com/taymath/tutortoolkit/studentdetail/StudentDetailViewModel.kt
new file mode 100644
index 0000000..93d27c1
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/studentdetail/StudentDetailViewModel.kt
@@ -0,0 +1,97 @@
+package com.taymath.tutortoolkit.studentdetail
+
+import androidx.lifecycle.*
+import com.taymath.tutortoolkit.studentdatabase.Student
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabaseDao
+import kotlinx.coroutines.*
+
+class StudentDetailViewModel(
+ val studentId: Long,
+ dataSource: StudentDatabaseDao
+): ViewModel() {
+
+ /**
+ * Hold a reference to StudentDatabase via its StudentDatabaseDao.
+ */
+ val database = dataSource
+
+ // Initialize mediatorLiveData with student datatype
+ private val student = MediatorLiveData()
+ fun getStudent() = student
+
+ // Grab grades from grades_table with StudentId
+ val grades = database.getGradesWithStudentId(studentId)
+
+ // add student from database as source for student
+ init {
+ student.addSource(database.getStudentWithId(studentId), student::setValue)
+ }
+
+ // Initialize viewModelJob
+ private val viewModelJob = Job()
+
+ // Initialize uiScope
+ private val uiScope = CoroutineScope(Dispatchers.Main + viewModelJob)
+
+ // Setup Livedata to signal when to navigate to AddGrade
+ private val _navigateToAddGrade = MutableLiveData()
+ val navigateToAddGrade: LiveData
+ get() = _navigateToAddGrade
+
+ // Setup Livedata to signal when to navigate to studentList
+ private val _navigateToStudentList = MutableLiveData()
+ val navigateToStudentList: LiveData
+ get() = _navigateToStudentList
+
+ // Setup Livedata to tell whethere the clear button should be visible
+ // Based on the contents of our grades list
+ val clearButtonVisible = Transformations.map(grades) {
+ it?.isNotEmpty()
+ }
+
+ fun onNavigateToStudentList() {
+ _navigateToStudentList.value = true
+ }
+
+ fun onNavigateToAddGrade() {
+ _navigateToAddGrade.value = true
+ }
+
+ override fun onCleared() {
+ super.onCleared()
+ viewModelJob.cancel()
+ }
+
+ fun doneNavigating() {
+ _navigateToAddGrade.value = null
+ _navigateToStudentList.value = null
+ }
+
+ fun onClear() {
+ uiScope.launch {
+ // Clear the database table.
+ clearGrades(studentId)
+ }
+ }
+
+ private suspend fun clearGrades(studentId: Long) {
+ withContext(Dispatchers.IO) {
+ database.deleteGradeTable(studentId)
+ }
+ }
+
+ private suspend fun deleteStudent(studentId: Long) {
+ withContext(Dispatchers.IO) {
+ database.deleteGradeTable(studentId)
+ database.deleteStudent(studentId)
+ }
+ }
+
+ fun onDeleteStudent() {
+ uiScope.launch {
+ deleteStudent(studentId)
+ }
+ _navigateToStudentList.value = true
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/taymath/tutortoolkit/studentdetail/StudentDetailViewModelFactory.kt b/app/src/main/java/com/taymath/tutortoolkit/studentdetail/StudentDetailViewModelFactory.kt
new file mode 100644
index 0000000..2ac0467
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/studentdetail/StudentDetailViewModelFactory.kt
@@ -0,0 +1,19 @@
+package com.taymath.tutortoolkit.studentdetail
+
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.taymath.tutortoolkit.studentdatabase.Student
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabaseDao
+
+class StudentDetailViewModelFactory(
+ private val dataSource: StudentDatabaseDao,
+ private val studentId: Long
+) : ViewModelProvider.Factory {
+ @Suppress("unchecked_cast")
+ override fun create(modelClass: Class): T {
+ if (modelClass.isAssignableFrom(StudentDetailViewModel::class.java)) {
+ return StudentDetailViewModel(studentId, dataSource) as T
+ }
+ throw IllegalArgumentException("Unknown ViewModel class")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/taymath/tutortoolkit/studentlist/StudentAdapter.kt b/app/src/main/java/com/taymath/tutortoolkit/studentlist/StudentAdapter.kt
new file mode 100644
index 0000000..40eafef
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/studentlist/StudentAdapter.kt
@@ -0,0 +1,55 @@
+package com.taymath.tutortoolkit.studentlist
+
+import android.view.LayoutInflater
+import android.view.ViewGroup
+import androidx.recyclerview.widget.DiffUtil
+import androidx.recyclerview.widget.ListAdapter
+import androidx.recyclerview.widget.RecyclerView
+import com.taymath.tutortoolkit.databinding.ListItemStudentBinding
+import com.taymath.tutortoolkit.studentdatabase.Student
+
+class StudentAdapter(val clickListener: StudentListener) : ListAdapter(StudentDiffCallback()) {
+
+ override fun onCreateViewHolder(parent: ViewGroup, viewType: Int): ViewHolder {
+ return ViewHolder.from(parent)
+ }
+
+
+ override fun onBindViewHolder(holder: ViewHolder, position: Int) {
+ holder.bind(clickListener, getItem(position)!!)
+ }
+
+
+ class ViewHolder private constructor(val binding: ListItemStudentBinding): RecyclerView.ViewHolder(binding.root) {
+
+ fun bind(clickListener: StudentListener, item: Student) {
+ binding.student = item
+ binding.clickListener = clickListener
+ binding.executePendingBindings()
+ }
+
+ companion object {
+ fun from(parent: ViewGroup): ViewHolder {
+ val layoutInflater = LayoutInflater.from(parent.context)
+ val binding = ListItemStudentBinding.inflate(layoutInflater, parent, false)
+ return ViewHolder(binding)
+ }
+ }
+
+ }
+
+ class StudentDiffCallback : DiffUtil.ItemCallback() {
+ override fun areItemsTheSame(oldItem: Student, newItem: Student): Boolean {
+ return oldItem.studentId == newItem.studentId
+ }
+
+ override fun areContentsTheSame(oldItem: Student, newItem: Student): Boolean {
+ return oldItem == newItem
+ }
+
+ }
+}
+
+class StudentListener(val clickListener: (studentId: Long) -> Unit) {
+ fun onClick(student: Student) = clickListener(student.studentId)
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/taymath/tutortoolkit/studentlist/StudentBindingUtils.kt b/app/src/main/java/com/taymath/tutortoolkit/studentlist/StudentBindingUtils.kt
new file mode 100644
index 0000000..d05eb10
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/studentlist/StudentBindingUtils.kt
@@ -0,0 +1,35 @@
+package com.taymath.tutortoolkit.studentlist
+
+import android.widget.ImageView
+import android.widget.TextView
+import androidx.databinding.BindingAdapter
+import com.taymath.tutortoolkit.R
+import com.taymath.tutortoolkit.studentdatabase.Student
+
+@BindingAdapter("studentImage")
+fun ImageView.setStudentImage(item: Student?){
+ item?.let {
+ setImageResource(R.drawable.ic_item_test)
+ }
+}
+
+@BindingAdapter("subjectText")
+fun TextView.setSubjectText(item: Student?){
+ item?.let {
+ text =item.subjectString
+ }
+}
+
+@BindingAdapter("studentNameText")
+fun TextView.setStudentNameText(item: Student?){
+ item?.let {
+ text =item.studentNameString
+ }
+}
+
+@BindingAdapter("gradeLevelText")
+fun TextView.setGradeLevelText(item: Student?){
+ item?.let {
+ text =item.gradeLevelString
+ }
+}
diff --git a/app/src/main/java/com/taymath/tutortoolkit/studentlist/StudentListFragment.kt b/app/src/main/java/com/taymath/tutortoolkit/studentlist/StudentListFragment.kt
new file mode 100644
index 0000000..c0efa9f
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/studentlist/StudentListFragment.kt
@@ -0,0 +1,88 @@
+package com.taymath.tutortoolkit.studentlist
+
+import android.os.Bundle
+import android.view.LayoutInflater
+import android.view.View
+import android.view.ViewGroup
+import androidx.databinding.DataBindingUtil
+import androidx.fragment.app.Fragment
+import androidx.lifecycle.Observer
+import androidx.lifecycle.ViewModelProviders
+import androidx.navigation.fragment.findNavController
+import com.taymath.tutortoolkit.R
+import com.taymath.tutortoolkit.databinding.FragmentStudentListBinding
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabase
+import kotlinx.android.synthetic.main.fragment_add_student.*
+
+/**
+ * A fragment with buttons to record start and end times for sleep, which are saved in
+ * a database. Cumulative data is displayed in a simple scrollable TextView.
+ * (Because we have not learned about RecyclerView yet.)
+ */
+class StudentListFragment : Fragment() {
+
+ /**
+ * Called when the Fragment is ready to display content to the screen.
+ *
+ * This function uses DataBindingUtil to inflate R.layout.fragment_get_todo.
+ */
+ override fun onCreateView(inflater: LayoutInflater, container: ViewGroup?,
+ savedInstanceState: Bundle?): View? {
+
+ // Get a reference to the binding object and inflate the fragment views.
+ val binding: FragmentStudentListBinding = DataBindingUtil.inflate(
+ inflater, R.layout.fragment_student_list, container, false)
+
+ // Get reference to application
+ val application = requireNotNull(this.activity).application
+
+ // Get a reference to the DAO
+ val dataSource = StudentDatabase.getInstance(application).studentDatabaseDao
+
+ // Create instance of viewModelFactory using DAO and application
+ val viewModelFactory = StudentListViewModelFactory(dataSource, application)
+
+ // Get reference to viewModel
+ val studentListViewModel =
+ ViewModelProviders.of(
+ this, viewModelFactory).get(StudentListViewModel::class.java)
+
+ // Add ViewModel to our binding
+ binding.studentListViewModel = studentListViewModel
+
+ binding.setLifecycleOwner(this)
+
+ // Add an Observer to the state variable for Navigating when Add Student button is clicked.
+ studentListViewModel.navigateToAddStudent.observe(viewLifecycleOwner, Observer {
+ if (it == true) { // Observed state is true.
+ this.findNavController().navigate(
+ StudentListFragmentDirections.actionStudentListFragmentToAddStudentFragment())
+ studentListViewModel.onAddStudentNavigated()
+ }
+ })
+
+ // Add an Observer to the state variable for Navigating when student icon is clicked.
+ studentListViewModel.navigateToStudentDetail.observe(viewLifecycleOwner, Observer {student ->
+ student?.let {
+ this.findNavController().navigate(StudentListFragmentDirections
+ .actionStudentListFragmentToStudentDetailFragment(student))
+ studentListViewModel.onStudentDetailNavigated()
+ }
+ })
+
+ // Initialize adapter and add to studentList
+ val adapter = StudentAdapter(StudentListener {
+ studentId -> studentListViewModel.onNavToStudentDetail(studentId)
+ })
+ binding.studentList.adapter = adapter
+
+ // If we have a list of students, send it to the adapter
+ studentListViewModel.students.observe(viewLifecycleOwner, Observer {
+ it?.let {
+ adapter.submitList(it)
+ }
+ })
+
+ return binding.root
+ }
+}
diff --git a/app/src/main/java/com/taymath/tutortoolkit/studentlist/StudentListViewModel.kt b/app/src/main/java/com/taymath/tutortoolkit/studentlist/StudentListViewModel.kt
new file mode 100644
index 0000000..5259802
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/studentlist/StudentListViewModel.kt
@@ -0,0 +1,57 @@
+package com.taymath.tutortoolkit.studentlist
+
+import android.app.Application
+import androidx.lifecycle.AndroidViewModel
+import androidx.lifecycle.LiveData
+import androidx.lifecycle.MutableLiveData
+import com.taymath.tutortoolkit.studentdatabase.Student
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabaseDao
+import kotlinx.coroutines.*
+
+class StudentListViewModel(
+ val database: StudentDatabaseDao,
+ application: Application
+) : AndroidViewModel(application) {
+
+ /** Coroutine setup variables */
+
+ /**
+ * viewModelJob allows us to cancel all coroutines started by this ViewModel.
+ */
+ private val viewModelJob = Job()
+
+ // Add variable to navigation signaller
+ private val _navigateToAddStudent = MutableLiveData()
+ val navigateToAddStudent: LiveData
+ get() = _navigateToAddStudent
+
+ private val _navigateToStudentDetail = MutableLiveData()
+ val navigateToStudentDetail: LiveData
+ get() = _navigateToStudentDetail
+
+ val students = database.getAllStudents()
+
+ override fun onCleared() {
+ super.onCleared()
+ viewModelJob.cancel()
+ }
+
+ // set navigate to student to be true when clicked
+ fun onNavToAddStudent() {
+ _navigateToAddStudent.value = true
+ }
+
+ // Reset nav value after navigation
+ fun onAddStudentNavigated() {
+ _navigateToAddStudent.value = null
+ }
+
+ fun onNavToStudentDetail(studentId: Long) {
+ _navigateToStudentDetail.value = studentId
+ }
+
+ fun onStudentDetailNavigated() {
+ _navigateToStudentDetail.value = null
+ }
+
+}
\ No newline at end of file
diff --git a/app/src/main/java/com/taymath/tutortoolkit/studentlist/StudentListViewModelFactory.kt b/app/src/main/java/com/taymath/tutortoolkit/studentlist/StudentListViewModelFactory.kt
new file mode 100644
index 0000000..50b84e8
--- /dev/null
+++ b/app/src/main/java/com/taymath/tutortoolkit/studentlist/StudentListViewModelFactory.kt
@@ -0,0 +1,18 @@
+package com.taymath.tutortoolkit.studentlist
+
+import android.app.Application
+import androidx.lifecycle.ViewModel
+import androidx.lifecycle.ViewModelProvider
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabaseDao
+
+class StudentListViewModelFactory(
+ private val dataSource: StudentDatabaseDao,
+ private val application: Application) : ViewModelProvider.Factory {
+ @Suppress("unchecked_cast")
+ override fun create(modelClass: Class): T {
+ if (modelClass.isAssignableFrom(StudentListViewModel::class.java)) {
+ return StudentListViewModel(dataSource, application) as T
+ }
+ throw IllegalArgumentException("Unknown ViewModel class")
+ }
+}
\ No newline at end of file
diff --git a/app/src/main/res/drawable-v24/ic_item_test.xml b/app/src/main/res/drawable-v24/ic_item_test.xml
new file mode 100644
index 0000000..da1dcd9
--- /dev/null
+++ b/app/src/main/res/drawable-v24/ic_item_test.xml
@@ -0,0 +1,31 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 0000000..2b068d1
--- /dev/null
+++ b/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/drawable/ic_launcher_background.xml b/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 0000000..ca3826a
--- /dev/null
+++ b/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,74 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/drawable/icon_1.png b/app/src/main/res/drawable/icon_1.png
new file mode 100644
index 0000000..39ca33a
Binary files /dev/null and b/app/src/main/res/drawable/icon_1.png differ
diff --git a/app/src/main/res/drawable/icon_2.png b/app/src/main/res/drawable/icon_2.png
new file mode 100644
index 0000000..ec9bddb
Binary files /dev/null and b/app/src/main/res/drawable/icon_2.png differ
diff --git a/app/src/main/res/drawable/icon_3.png b/app/src/main/res/drawable/icon_3.png
new file mode 100644
index 0000000..f1d8ed1
Binary files /dev/null and b/app/src/main/res/drawable/icon_3.png differ
diff --git a/app/src/main/res/drawable/icon_4.png b/app/src/main/res/drawable/icon_4.png
new file mode 100644
index 0000000..730d8e0
Binary files /dev/null and b/app/src/main/res/drawable/icon_4.png differ
diff --git a/app/src/main/res/drawable/icon_5.png b/app/src/main/res/drawable/icon_5.png
new file mode 100644
index 0000000..a5f34fe
Binary files /dev/null and b/app/src/main/res/drawable/icon_5.png differ
diff --git a/app/src/main/res/drawable/icon_6.png b/app/src/main/res/drawable/icon_6.png
new file mode 100644
index 0000000..612dab1
Binary files /dev/null and b/app/src/main/res/drawable/icon_6.png differ
diff --git a/app/src/main/res/drawable/icon_7.png b/app/src/main/res/drawable/icon_7.png
new file mode 100644
index 0000000..747b831
Binary files /dev/null and b/app/src/main/res/drawable/icon_7.png differ
diff --git a/app/src/main/res/drawable/icon_8.png b/app/src/main/res/drawable/icon_8.png
new file mode 100644
index 0000000..76fea58
Binary files /dev/null and b/app/src/main/res/drawable/icon_8.png differ
diff --git a/app/src/main/res/layout/activity_main.xml b/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 0000000..73c4f2d
--- /dev/null
+++ b/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,16 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_add_grade.xml b/app/src/main/res/layout/fragment_add_grade.xml
new file mode 100644
index 0000000..0bd2f28
--- /dev/null
+++ b/app/src/main/res/layout/fragment_add_grade.xml
@@ -0,0 +1,84 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_add_student.xml b/app/src/main/res/layout/fragment_add_student.xml
new file mode 100644
index 0000000..7efc059
--- /dev/null
+++ b/app/src/main/res/layout/fragment_add_student.xml
@@ -0,0 +1,120 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_choose_icon.xml b/app/src/main/res/layout/fragment_choose_icon.xml
new file mode 100644
index 0000000..7a7bd6e
--- /dev/null
+++ b/app/src/main/res/layout/fragment_choose_icon.xml
@@ -0,0 +1,58 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/main/res/layout/fragment_student_detail.xml b/app/src/main/res/layout/fragment_student_detail.xml
new file mode 100644
index 0000000..c2b5029
--- /dev/null
+++ b/app/src/main/res/layout/fragment_student_detail.xml
@@ -0,0 +1,85 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/fragment_student_list.xml b/app/src/main/res/layout/fragment_student_list.xml
new file mode 100644
index 0000000..5fb46f7
--- /dev/null
+++ b/app/src/main/res/layout/fragment_student_list.xml
@@ -0,0 +1,40 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/list_item_grade.xml b/app/src/main/res/layout/list_item_grade.xml
new file mode 100644
index 0000000..8e86c88
--- /dev/null
+++ b/app/src/main/res/layout/list_item_grade.xml
@@ -0,0 +1,53 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/layout/list_item_student.xml b/app/src/main/res/layout/list_item_student.xml
new file mode 100644
index 0000000..8e51f36
--- /dev/null
+++ b/app/src/main/res/layout/list_item_student.xml
@@ -0,0 +1,72 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 0000000..c4a603d
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 0000000..c4a603d
--- /dev/null
+++ b/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/app/src/main/res/mipmap-hdpi/ic_launcher.png
new file mode 100644
index 0000000..3c5de8c
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..2779586
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher_round.png b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png
new file mode 100644
index 0000000..0785b36
Binary files /dev/null and b/app/src/main/res/mipmap-hdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/app/src/main/res/mipmap-mdpi/ic_launcher.png
new file mode 100644
index 0000000..3a1b83f
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..259aaa0
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher_round.png b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png
new file mode 100644
index 0000000..f3b2e01
Binary files /dev/null and b/app/src/main/res/mipmap-mdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/app/src/main/res/mipmap-xhdpi/ic_launcher.png
new file mode 100644
index 0000000..a60320a
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..096f737
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..a74cc33
Binary files /dev/null and b/app/src/main/res/mipmap-xhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png
new file mode 100644
index 0000000..1312f4a
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..49b33f6
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..35d9fbd
Binary files /dev/null and b/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png
new file mode 100644
index 0000000..5aeadfc
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png
new file mode 100644
index 0000000..1ea8012
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_foreground.png differ
diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png
new file mode 100644
index 0000000..ba5bbf6
Binary files /dev/null and b/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.png differ
diff --git a/app/src/main/res/navigation/navigation.xml b/app/src/main/res/navigation/navigation.xml
new file mode 100644
index 0000000..a20efd7
--- /dev/null
+++ b/app/src/main/res/navigation/navigation.xml
@@ -0,0 +1,59 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/app/src/main/res/values/colors.xml b/app/src/main/res/values/colors.xml
new file mode 100644
index 0000000..f016d89
--- /dev/null
+++ b/app/src/main/res/values/colors.xml
@@ -0,0 +1,13 @@
+
+
+ #6ab343
+ #388310
+ #6ab343
+
+ #388310
+ #f0f0f0
+
+ #DC2828
+ #F44B03
+ #040404
+
diff --git a/app/src/main/res/values/dimens.xml b/app/src/main/res/values/dimens.xml
new file mode 100644
index 0000000..1d971f1
--- /dev/null
+++ b/app/src/main/res/values/dimens.xml
@@ -0,0 +1,7 @@
+
+
+ 16dp
+ 64dp
+ 20sp
+ 48dp
+
diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml
new file mode 100644
index 0000000..ee4b651
--- /dev/null
+++ b/app/src/main/res/values/strings.xml
@@ -0,0 +1,26 @@
+
+ TutorToolkit
+ Student Name
+ Subject
+ Grade Level
+ Address
+ Email
+ Add Student
+ Image representing student
+ Delete
+ Graph of Grades
+ Graph of students\' grades
+ 90%
+ A
+ Example Note Here!
+ Add Grade
+ TextView
+ Decimal Grade
+ Letter Grade
+ Notes
+ Clear Grades
+ Delete Student
+ Student Image Icon Choice
+ Icon 1
+ Choose Your Icon!
+
diff --git a/app/src/main/res/values/styles.xml b/app/src/main/res/values/styles.xml
new file mode 100644
index 0000000..c248d03
--- /dev/null
+++ b/app/src/main/res/values/styles.xml
@@ -0,0 +1,21 @@
+
+
+
+
+
+
+
+
+
+
diff --git a/app/src/test/java/com/taymath/tutortoolkit/ExampleUnitTest.kt b/app/src/test/java/com/taymath/tutortoolkit/ExampleUnitTest.kt
new file mode 100644
index 0000000..d6c4f2b
--- /dev/null
+++ b/app/src/test/java/com/taymath/tutortoolkit/ExampleUnitTest.kt
@@ -0,0 +1,59 @@
+package com.taymath.tutortoolkit
+
+import android.content.Context
+import androidx.room.Room
+import androidx.test.platform.app.InstrumentationRegistry
+import com.taymath.tutortoolkit.studentdatabase.Grade
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabase
+import com.taymath.tutortoolkit.studentdatabase.StudentDatabaseDao
+import org.hamcrest.CoreMatchers.equalTo
+import org.junit.After
+import org.junit.Test
+
+import org.junit.Assert.*
+import org.junit.Before
+import org.junit.runner.RunWith
+import org.junit.runners.JUnit4
+import java.io.IOException
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * See [testing documentation](http://d.android.com/tools/testing).
+ */
+class ExampleUnitTest {
+ @Test
+ fun addition_isCorrect() {
+ assertEquals(4, 2 + 2)
+ }
+}
+
+@RunWith(JUnit4::class)
+class SimpleEntityReadWriteTest {
+ private lateinit var userDao: StudentDatabaseDao
+ private lateinit var db: StudentDatabase
+
+ @Before
+ fun createDb() {
+ val context = InstrumentationRegistry.getInstrumentation().getTargetContext()
+ db = Room.inMemoryDatabaseBuilder(
+ context, StudentDatabase::class.java
+ ).build()
+ userDao = db.studentDatabaseDao
+ }
+
+ @After
+ @Throws(IOException::class)
+ fun closeDb() {
+ db.close()
+ }
+
+ @Test
+ @Throws(Exception::class)
+ fun writeUserAndReadInList() {
+ val grade: Grade = Grade()
+ userDao.insertGrade(grade)
+ val byName = userDao.getGrade()
+ assertThat(byName, equalTo(grade))
+ }
+}
\ No newline at end of file
diff --git a/build.gradle b/build.gradle
new file mode 100644
index 0000000..f7a2900
--- /dev/null
+++ b/build.gradle
@@ -0,0 +1,41 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+
+buildscript {
+ ext {
+ version_core = "1.0.1"
+ version_coroutine = "1.1.0"
+ version_navigation = '1.0.0'
+ version_constraint_layout = "2.0.0-alpha3"
+ version_gradle = '3.3.2'
+ version_kotlin = "1.3.21"
+ version_lifecycle_extensions = "2.0.0"
+ version_room = "2.0.0"
+ version_appcompat = "1.0.2"
+ version_fragment = "1.0.0"
+ }
+ repositories {
+ google()
+ jcenter()
+
+ }
+ dependencies {
+ classpath 'com.android.tools.build:gradle:3.6.2'
+ classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$version_kotlin"
+ classpath "android.arch.navigation:navigation-safe-args-gradle-plugin:$version_navigation"
+
+ // NOTE: Do not place your application dependencies here; they belong
+ // in the individual module build.gradle files
+ }
+}
+
+allprojects {
+ repositories {
+ google()
+ jcenter()
+
+ }
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
diff --git a/gradle.properties b/gradle.properties
new file mode 100644
index 0000000..23339e0
--- /dev/null
+++ b/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx1536m
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app's APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Automatically convert third-party libraries to use AndroidX
+android.enableJetifier=true
+# Kotlin code style for this project: "official" or "obsolete":
+kotlin.code.style=official
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 0000000..f6b961f
Binary files /dev/null and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 0000000..bb40496
--- /dev/null
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,6 @@
+#Fri Apr 10 13:29:17 PDT 2020
+distributionBase=GRADLE_USER_HOME
+distributionPath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
+zipStorePath=wrapper/dists
+distributionUrl=https\://services.gradle.org/distributions/gradle-5.6.4-all.zip
diff --git a/gradlew b/gradlew
new file mode 100644
index 0000000..cccdd3d
--- /dev/null
+++ b/gradlew
@@ -0,0 +1,172 @@
+#!/usr/bin/env sh
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS=""
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin, switch paths to Windows format before running java
+if $cygwin ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=$((i+1))
+ done
+ case $i in
+ (0) set -- ;;
+ (1) set -- "$args0" ;;
+ (2) set -- "$args0" "$args1" ;;
+ (3) set -- "$args0" "$args1" "$args2" ;;
+ (4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=$(save "$@")
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
+if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
+ cd "$(dirname "$0")"
+fi
+
+exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
new file mode 100644
index 0000000..f955316
--- /dev/null
+++ b/gradlew.bat
@@ -0,0 +1,84 @@
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS=
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto init
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto init
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:init
+@rem Get command-line arguments, handling Windows variants
+
+if not "%OS%" == "Windows_NT" goto win9xME_args
+
+:win9xME_args
+@rem Slurp the command line arguments.
+set CMD_LINE_ARGS=
+set _SKIP=2
+
+:win9xME_args_slurp
+if "x%~1" == "x" goto execute
+
+set CMD_LINE_ARGS=%*
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/settings.gradle b/settings.gradle
new file mode 100644
index 0000000..9e246cf
--- /dev/null
+++ b/settings.gradle
@@ -0,0 +1,2 @@
+rootProject.name='TutorToolkit'
+include ':app'