diff --git a/app/build.gradle b/app/build.gradle index 5c6b306..f6c0cdc 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -1,11 +1,21 @@ apply plugin: 'com.android.application' apply plugin: 'kotlin-android' +apply plugin: 'kotlin-kapt' apply plugin: 'kotlin-android-extensions' android { compileSdkVersion 29 buildToolsVersion "29.0.3" + dataBinding { + enabled = true + } + + configurations.all() { + resolutionStrategy.force "org.antlr:antlr4-runtime:4.5.3" + resolutionStrategy.force "org.antlr:antlr4-tool:4.5.3" + } + defaultConfig { applicationId "fr.sanchezm.attestationsCovid19" minSdkVersion 23 @@ -26,7 +36,6 @@ android { // To inline the bytecode built with JVM target 1.8 into // bytecode that is being built with JVM target 1.6. (e.g. navArgs) - compileOptions { sourceCompatibility JavaVersion.VERSION_1_8 targetCompatibility JavaVersion.VERSION_1_8 @@ -46,10 +55,21 @@ dependencies { implementation 'androidx.constraintlayout:constraintlayout:1.1.3' implementation 'androidx.navigation:navigation-fragment:2.2.1' implementation 'androidx.navigation:navigation-ui:2.2.1' - implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' + implementation 'androidx.navigation:navigation-fragment-ktx:2.2.1' implementation 'androidx.navigation:navigation-ui-ktx:2.2.1' + + // Room + implementation 'androidx.room:room-runtime:2.2.5' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' + implementation 'androidx.lifecycle:lifecycle-extensions:2.2.0' + implementation 'androidx.lifecycle:lifecycle-viewmodel-ktx:2.2.0' + kapt 'androidx.room:room-compiler:2.2.5' + +// kapt 'com.android.databinding:compiler:3.1.4' + testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test.ext:junit:1.1.1' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' + implementation 'androidx.legacy:legacy-support-v4:1.0.0' } diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/MainActivity.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/MainActivity.kt index e6ff040..bb20fda 100644 --- a/app/src/main/java/fr/sanchezm/attestationsCovid19/MainActivity.kt +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/MainActivity.kt @@ -11,11 +11,11 @@ class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) + val navView: BottomNavigationView = findViewById(R.id.nav_view) val navController = findNavController(R.id.nav_host_fragment) - navController actionBar?.hide() navView.setupWithNavController(navController) navView.setBackgroundColor(resources.getColor(R.color.itemBackground, theme)) diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/data/db/MyDatabase.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/data/db/MyDatabase.kt new file mode 100644 index 0000000..948fdf8 --- /dev/null +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/data/db/MyDatabase.kt @@ -0,0 +1,34 @@ +package fr.sanchezm.attestationsCovid19.data.db + +import android.content.Context +import androidx.room.Database +import androidx.room.Room +import androidx.room.RoomDatabase +import fr.sanchezm.attestationsCovid19.data.db.dao.ProfileDao +import fr.sanchezm.attestationsCovid19.data.db.entity.Profile + +@Database( + entities = [Profile::class], + version = 1 +) +abstract class MyDatabase private constructor() : RoomDatabase() { + + abstract fun profileDao(): ProfileDao + + companion object { + @Volatile + private var instance: MyDatabase? = null + private val LOCK = Any() + + operator fun invoke(context: Context) = instance ?: synchronized(LOCK) { + instance ?: buildDatabase(context).also { instance = it } + } + + private fun buildDatabase(context: Context) = + Room.databaseBuilder( + context.applicationContext, + MyDatabase::class.java, "data.db" + ) + .build() + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/data/db/dao/ProfileDao.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/data/db/dao/ProfileDao.kt new file mode 100644 index 0000000..0d8d6a0 --- /dev/null +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/data/db/dao/ProfileDao.kt @@ -0,0 +1,18 @@ +package fr.sanchezm.attestationsCovid19.data.db.dao + +import androidx.lifecycle.LiveData +import androidx.room.Dao +import androidx.room.Insert +import androidx.room.OnConflictStrategy +import androidx.room.Query +import fr.sanchezm.attestationsCovid19.data.db.entity.CURRENT_PROFILE_ID +import fr.sanchezm.attestationsCovid19.data.db.entity.Profile + +@Dao +interface ProfileDao { + @Insert(onConflict = OnConflictStrategy.REPLACE) + fun insert(profile: Profile) + + @Query(value = "SELECT * FROM profile WHERE id = $CURRENT_PROFILE_ID") + fun getProfile(): LiveData +} \ No newline at end of file diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/data/db/entity/Profile.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/data/db/entity/Profile.kt new file mode 100644 index 0000000..76decc6 --- /dev/null +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/data/db/entity/Profile.kt @@ -0,0 +1,29 @@ +package fr.sanchezm.attestationsCovid19.data.db.entity + +import androidx.room.Entity +import androidx.room.PrimaryKey + +const val CURRENT_PROFILE_ID = 0 + +@Entity(tableName = "profile") +data class Profile( + val firstName: String, + val lastName: String, + val birthday: String, + val birthPlace: String, + val address: String, + val city: String, + val postalCode: String +) { + @PrimaryKey + var id: Int = CURRENT_PROFILE_ID + + override fun toString(): String { + val builder = StringBuilder() + builder.append("Nom:", lastName, "; ") + builder.append("Prenom:", firstName, "; ") + builder.append("Naissance:", birthday, " a ", birthPlace, "; ") + builder.append("Adresse:", address, " ", postalCode, " ", city, "; ") + return builder.toString() + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/data/repository/ProfileRepository.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/data/repository/ProfileRepository.kt new file mode 100644 index 0000000..1d02318 --- /dev/null +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/data/repository/ProfileRepository.kt @@ -0,0 +1,21 @@ +package fr.sanchezm.attestationsCovid19.data.repository + +import fr.sanchezm.attestationsCovid19.data.db.dao.ProfileDao +import fr.sanchezm.attestationsCovid19.data.db.entity.Profile + +class ProfileRepository private constructor(private val profileDao: ProfileDao) { + + fun getProfile() = profileDao.getProfile() + + fun insertProfile(profile: Profile) = profileDao.insert(profile) + + companion object { + @Volatile + private var instance: ProfileRepository? = null + + fun getInstance(profileDao: ProfileDao) = + instance ?: synchronized(this) { + instance ?: ProfileRepository(profileDao).also { instance = it } + } + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddFragment.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddFragment.kt index 8472c62..fb8722e 100644 --- a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddFragment.kt +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddFragment.kt @@ -4,25 +4,41 @@ 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.lifecycle.ViewModelProvider import fr.sanchezm.attestationsCovid19.R +import fr.sanchezm.attestationsCovid19.databinding.FragmentAddAttestationBinding +import fr.sanchezm.attestationsCovid19.utilities.InjectorUtils class AddFragment : Fragment() { - private lateinit var homeViewModel: AddViewModel + private lateinit var addViewModel: AddViewModel override fun onCreateView( inflater: LayoutInflater, container: ViewGroup?, savedInstanceState: Bundle? ): View? { - homeViewModel = - ViewModelProviders.of(this).get(AddViewModel::class.java) - val root = inflater.inflate(R.layout.fragment_add_attestation, container, false) - homeViewModel.text.observe(viewLifecycleOwner, Observer { - }) - return root + initializeUi() + val binding = DataBindingUtil.inflate( + inflater, + R.layout.fragment_add_attestation, + container, + false + ).apply { + this.lifecycleOwner = this@AddFragment + this.viewModel = addViewModel + } + + return binding.root + } + + private fun initializeUi() { + val factory = context?.let { InjectorUtils.provideAddViewModelFactory(it) } + addViewModel = factory?.let { + ViewModelProvider(this, it) + .get(AddViewModel::class.java) + }!! } } diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddViewModel.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddViewModel.kt index 9f111d2..8aa1bd7 100644 --- a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddViewModel.kt +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddViewModel.kt @@ -1,13 +1,69 @@ package fr.sanchezm.attestationsCovid19.ui.add -import androidx.lifecycle.LiveData +import android.annotation.SuppressLint +import android.util.Log import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel +import fr.sanchezm.attestationsCovid19.data.db.entity.Profile +import fr.sanchezm.attestationsCovid19.data.repository.ProfileRepository -class AddViewModel : ViewModel() { +class AddViewModel(private val profileRepository: ProfileRepository) : ViewModel() { - private val _text = MutableLiveData().apply { - value = "Fragment ajouter une attestation" + val firstName = MutableLiveData() + val lastName = MutableLiveData() + val birthday = MutableLiveData() + val birthPlace = MutableLiveData() + val address = MutableLiveData() + val city = MutableLiveData() + val postalCode = MutableLiveData() + val exitDate = MutableLiveData() + val exitHour = MutableLiveData() + + @SuppressLint("LongLogTag") + fun onGenerateAttestationClick() { + if (checkAllValue()) { + profileRepository.insertProfile(getProfileFromView()) + } else { + Log.e("onGenerateAttestationClick", "Cannot add profile") + } } - val text: LiveData = _text + + init { + setProfileValue() + } + + private fun setProfileValue() { + val profile = profileRepository.getProfile() + + firstName.value = profile.value?.firstName + lastName.value = profile.value?.lastName + birthday.value = profile.value?.birthday + birthPlace.value = profile.value?.birthPlace + address.value = profile.value?.address + city.value = profile.value?.city + postalCode.value = profile.value?.postalCode + } + + private fun getProfileFromView(): Profile { + return Profile( + firstName.value.toString(), + lastName.value.toString(), + birthday.value.toString(), + birthPlace.value.toString(), + address.value.toString(), + city.value.toString(), + postalCode.value.toString() + ) + } + + private fun checkAllValue(): Boolean { + return !firstName.value.isNullOrEmpty() + && !lastName.value.isNullOrEmpty() + && !birthday.value.isNullOrEmpty() + && !birthPlace.value.isNullOrEmpty() + && !address.value.isNullOrEmpty() + && !city.value.isNullOrEmpty() + && !postalCode.value.isNullOrEmpty() + } + } \ No newline at end of file diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddViewModelFactory.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddViewModelFactory.kt new file mode 100644 index 0000000..f8fcbf9 --- /dev/null +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/ui/add/AddViewModelFactory.kt @@ -0,0 +1,14 @@ +package fr.sanchezm.attestationsCovid19.ui.add + +import androidx.lifecycle.ViewModel +import androidx.lifecycle.ViewModelProvider +import fr.sanchezm.attestationsCovid19.data.repository.ProfileRepository + +class AddViewModelFactory(private val profileRepository: ProfileRepository) : + ViewModelProvider.NewInstanceFactory() { + + @Suppress("UNCHECKED_CAST") + override fun create(modelClass: Class): T { + return AddViewModel(profileRepository) as T + } +} \ No newline at end of file diff --git a/app/src/main/java/fr/sanchezm/attestationsCovid19/utilities/InjectorUtils.kt b/app/src/main/java/fr/sanchezm/attestationsCovid19/utilities/InjectorUtils.kt new file mode 100644 index 0000000..b4f082b --- /dev/null +++ b/app/src/main/java/fr/sanchezm/attestationsCovid19/utilities/InjectorUtils.kt @@ -0,0 +1,16 @@ +package fr.sanchezm.attestationsCovid19.utilities + +import android.content.Context +import fr.sanchezm.attestationsCovid19.data.db.MyDatabase +import fr.sanchezm.attestationsCovid19.data.repository.ProfileRepository +import fr.sanchezm.attestationsCovid19.ui.add.AddViewModelFactory + +object InjectorUtils { + + fun provideAddViewModelFactory(context: Context): AddViewModelFactory { + val profileRepository = + ProfileRepository.getInstance(MyDatabase.invoke(context).profileDao()) + + return AddViewModelFactory(profileRepository = profileRepository) + } +} \ No newline at end of file diff --git a/app/src/main/res/layout/fragment_add_attestation.xml b/app/src/main/res/layout/fragment_add_attestation.xml index 88c3c26..41e91cb 100644 --- a/app/src/main/res/layout/fragment_add_attestation.xml +++ b/app/src/main/res/layout/fragment_add_attestation.xml @@ -1,234 +1,256 @@ - + xmlns:app="http://schemas.android.com/apk/res-auto"> - + + + + + + tools:context=".ui.add.AddFragment"> - + android:layout_height="match_parent" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent"> - + android:orientation="vertical" + android:paddingHorizontal="50dp" + android:paddingVertical="20dp"> - - - - - + android:text="@string/attestation_title" + android:textColor="?attr/colorPrimary" + android:textSize="25sp" /> - - - - - + android:layout_marginBottom="20dp" + android:text="@string/attestation_subtitle" + android:textColor="?attr/colorAccent" + android:textSize="15sp" /> - - - - - + android:hint="@string/first_name"> - + - + - + android:hint="@string/last_name"> - + - + - + android:hint="@string/birthday"> - + - + - + android:hint="@string/birth_place"> - + - + - + android:hint="@string/address"> - + - + - + android:hint="@string/city"> - + - + - + android:hint="@string/postal_code"> - + - + - + - + - + - + - + - + - + - + - + - + - \ No newline at end of file + + + + + + + + + + + + + + + + + + + diff --git a/settings.gradle b/settings.gradle index c80e1ae..eb09dd5 100644 --- a/settings.gradle +++ b/settings.gradle @@ -1,2 +1,2 @@ -rootProject.name='My Application' +rootProject.name='Attestation Dérogatoire de déplacement COVID-19' include ':app'