diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionDispatcherFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionDispatcherFragmentTest.kt index a38a450fb4c0e196fe4c649f9a90572dac191aac..3b63821e006fe20b28a940bd38b4946118dc5f84 100644 --- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionDispatcherFragmentTest.kt +++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/submission/SubmissionDispatcherFragmentTest.kt @@ -12,9 +12,12 @@ import androidx.test.internal.runner.junit4.statement.UiThreadStatement.runOnUiT import dagger.Module import dagger.android.ContributesAndroidInjector import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.coronatest.antigen.profile.RATProfileSettings import de.rki.coronawarnapp.ui.submission.fragment.SubmissionDispatcherFragment import de.rki.coronawarnapp.ui.submission.viewmodel.SubmissionDispatcherViewModel import io.mockk.MockKAnnotations +import io.mockk.every +import io.mockk.impl.annotations.MockK import org.junit.After import org.junit.Before import org.junit.Rule @@ -23,9 +26,11 @@ import org.junit.runner.RunWith import testhelpers.BaseUITest import testhelpers.Screenshot import testhelpers.SystemUIDemoModeRule +import testhelpers.TestDispatcherProvider import testhelpers.captureScreenshot import testhelpers.launchFragment2 import testhelpers.launchFragmentInContainer2 +import testhelpers.preferences.mockFlowPreference import testhelpers.takeScreenshot import tools.fastlane.screengrab.locale.LocaleTestRule @@ -39,7 +44,12 @@ class SubmissionDispatcherFragmentTest : BaseUITest() { @get:Rule val systemUIDemoModeRule = SystemUIDemoModeRule() - private fun createViewModel() = SubmissionDispatcherViewModel() + @MockK lateinit var ratProfileSettings: RATProfileSettings + + private fun createViewModel() = SubmissionDispatcherViewModel( + ratProfileSettings, + TestDispatcherProvider() + ) private val navController = TestNavHostController( ApplicationProvider.getApplicationContext() @@ -50,6 +60,7 @@ class SubmissionDispatcherFragmentTest : BaseUITest() { @Before fun setup() { MockKAnnotations.init(this, relaxed = true) + every { ratProfileSettings.profile } returns mockFlowPreference(null) setupMockViewModel( object : SubmissionDispatcherViewModel.Factory { override fun create(): SubmissionDispatcherViewModel = createViewModel() diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/antigen/profile/RATProfile.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/antigen/profile/RATProfile.kt new file mode 100644 index 0000000000000000000000000000000000000000..53b97da250b79bc29e8929aacc7492d31c221222 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/antigen/profile/RATProfile.kt @@ -0,0 +1,15 @@ +package de.rki.coronawarnapp.coronatest.antigen.profile + +import com.google.gson.annotations.SerializedName +import org.joda.time.LocalDate + +data class RATProfile( + @SerializedName("firstName") val firstName: String, + @SerializedName("lastName") val lastName: String, + @SerializedName("birthDate") val birthDate: LocalDate?, + @SerializedName("street") val street: String, + @SerializedName("zipCode") val zipCode: String, + @SerializedName("city") val city: String, + @SerializedName("phone") val phone: String, + @SerializedName("email") val email: String, +) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/antigen/profile/RATProfileSettings.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/antigen/profile/RATProfileSettings.kt new file mode 100644 index 0000000000000000000000000000000000000000..a9169309856e9b587dcf33eda9217066c637d026 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/coronatest/antigen/profile/RATProfileSettings.kt @@ -0,0 +1,43 @@ +package de.rki.coronawarnapp.coronatest.antigen.profile + +import android.content.Context +import com.google.gson.Gson +import dagger.Reusable +import de.rki.coronawarnapp.util.di.AppContext +import de.rki.coronawarnapp.util.preferences.clearAndNotify +import de.rki.coronawarnapp.util.preferences.createFlowPreference +import de.rki.coronawarnapp.util.serialization.BaseGson +import de.rki.coronawarnapp.util.serialization.fromJson +import javax.inject.Inject + +@Reusable +class RATProfileSettings @Inject constructor( + @AppContext private val context: Context, + @BaseGson private val gson: Gson +) { + + private val prefs by lazy { + context.getSharedPreferences("ratprofile_localdata", Context.MODE_PRIVATE) + } + + val profile = prefs.createFlowPreference( + key = PREFS_KEY_PROFILE, + reader = { key -> + val rawProfile = getString(key, null) + if (rawProfile == null) { + null + } else { + gson.fromJson<RATProfile>(rawProfile) + } + }, + writer = { key, value -> + putString(key, gson.toJson(value)) + } + ) + + fun clear() = prefs.clearAndNotify() + + companion object { + private const val PREFS_KEY_PROFILE = "ratprofile.settings.profile" + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/RATProfileUIModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/RATProfileUIModule.kt new file mode 100644 index 0000000000000000000000000000000000000000..21a76225622d3fe5375e956e10c0bd7507114bb4 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/RATProfileUIModule.kt @@ -0,0 +1,13 @@ +package de.rki.coronawarnapp.ui.coronatest.rat.profile + +import dagger.Module +import dagger.android.ContributesAndroidInjector +import de.rki.coronawarnapp.ui.coronatest.rat.profile.create.RATProfileCreateFragment +import de.rki.coronawarnapp.ui.coronatest.rat.profile.create.RATProfileCreateFragmentModule + +@Module +internal abstract class RATProfileUIModule { + + @ContributesAndroidInjector(modules = [RATProfileCreateFragmentModule::class]) + abstract fun ratProfileCreateFragment(): RATProfileCreateFragment +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/CreateRATProfileNavigation.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/CreateRATProfileNavigation.kt new file mode 100644 index 0000000000000000000000000000000000000000..3db3b2611041bbf2f8e61aab33c1738d3ed63dec --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/CreateRATProfileNavigation.kt @@ -0,0 +1,6 @@ +package de.rki.coronawarnapp.ui.coronatest.rat.profile.create + +sealed class CreateRATProfileNavigation { + object Back : CreateRATProfileNavigation() + object ProfileScreen : CreateRATProfileNavigation() +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileCreateFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileCreateFragment.kt new file mode 100644 index 0000000000000000000000000000000000000000..8d32df661e7f5e6e1d971edf6c3c842de2e9b356 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileCreateFragment.kt @@ -0,0 +1,85 @@ +package de.rki.coronawarnapp.ui.coronatest.rat.profile.create + +import android.os.Bundle +import android.view.View +import androidx.core.widget.doAfterTextChanged +import androidx.fragment.app.Fragment +import com.google.android.material.datepicker.MaterialDatePicker +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.contactdiary.util.hideKeyboard +import de.rki.coronawarnapp.databinding.RatProfileCreateFragmentBinding +import de.rki.coronawarnapp.util.di.AutoInject +import de.rki.coronawarnapp.util.ui.doNavigate +import de.rki.coronawarnapp.util.ui.popBackStack +import de.rki.coronawarnapp.util.ui.viewBindingLazy +import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactoryProvider +import de.rki.coronawarnapp.util.viewmodel.cwaViewModels +import org.joda.time.LocalDate +import javax.inject.Inject + +class RATProfileCreateFragment : Fragment(R.layout.rat_profile_create_fragment), AutoInject { + @Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory + + private val binding: RatProfileCreateFragmentBinding by viewBindingLazy() + private val viewModel: RATProfileCreateFragmentViewModel by cwaViewModels { viewModelFactory } + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) = + with(binding) { + toolbar.setNavigationOnClickListener { + viewModel.navigateBack() + } + + profileSaveButton.setOnClickListener { + it.hideKeyboard() + viewModel.createProfile() + } + + // Full name + firstNameInputEdit.doAfterTextChanged { viewModel.firstNameChanged(it.toString()) } + lastNameInputEdit.doAfterTextChanged { viewModel.lastNameChanged(it.toString()) } + + // Birth date + birthDateInputEdit.setOnClickListener { openDatePicker() } + + // Address + streetInputEdit.doAfterTextChanged { viewModel.streetChanged(it.toString()) } + zipCodeInputEdit.doAfterTextChanged { viewModel.zipCodeChanged(it.toString()) } + cityInputEdit.doAfterTextChanged { viewModel.cityChanged(it.toString()) } + + // Phone + phoneInputEdit.doAfterTextChanged { viewModel.phoneChanged(it.toString()) } + + // E-mail + emailInputEdit.doAfterTextChanged { viewModel.emailChanged(it.toString()) } + + viewModel.profile.observe(viewLifecycleOwner) { + profileSaveButton.isEnabled = it?.isValid == true + } + + viewModel.events.observe(viewLifecycleOwner) { + when (it) { + CreateRATProfileNavigation.Back -> popBackStack() + CreateRATProfileNavigation.ProfileScreen -> doNavigate( + RATProfileCreateFragmentDirections + .actionRatProfileCreateFragmentToRatProfileQrCodeFragment() + ) + } + } + } + + private fun openDatePicker() { + MaterialDatePicker.Builder + .datePicker() + .build() + .apply { + addOnPositiveButtonClickListener { timestamp -> + val localDate = LocalDate(timestamp) + binding.birthDateInputEdit.setText( + localDate.toString("dd.MM.yyyy") + ) + viewModel.birthDateChanged(localDate) + } + } + .show(childFragmentManager, "RATProfileCreateFragment.MaterialDatePicker") + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileCreateFragmentModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileCreateFragmentModule.kt new file mode 100644 index 0000000000000000000000000000000000000000..70b073e2d5e89750bc0dcda057f4f5accdd53bc0 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileCreateFragmentModule.kt @@ -0,0 +1,18 @@ +package de.rki.coronawarnapp.ui.coronatest.rat.profile.create + +import dagger.Binds +import dagger.Module +import dagger.multibindings.IntoMap +import de.rki.coronawarnapp.util.viewmodel.CWAViewModel +import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactory +import de.rki.coronawarnapp.util.viewmodel.CWAViewModelKey + +@Module +abstract class RATProfileCreateFragmentModule { + @Binds + @IntoMap + @CWAViewModelKey(RATProfileCreateFragmentViewModel::class) + abstract fun ratProfileCreateFragmentViewModel( + factory: RATProfileCreateFragmentViewModel.Factory + ): CWAViewModelFactory<out CWAViewModel> +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileCreateFragmentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileCreateFragmentViewModel.kt new file mode 100644 index 0000000000000000000000000000000000000000..36ca71e288a1a5d80f7ae3fc88c57e7161ca3473 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileCreateFragmentViewModel.kt @@ -0,0 +1,86 @@ +package de.rki.coronawarnapp.ui.coronatest.rat.profile.create + +import androidx.lifecycle.LiveData +import androidx.lifecycle.MutableLiveData +import dagger.assisted.AssistedFactory +import dagger.assisted.AssistedInject +import de.rki.coronawarnapp.coronatest.antigen.profile.RATProfileSettings +import de.rki.coronawarnapp.util.ui.SingleLiveEvent +import de.rki.coronawarnapp.util.viewmodel.CWAViewModel +import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory +import org.joda.time.LocalDate +import timber.log.Timber + +class RATProfileCreateFragmentViewModel @AssistedInject constructor( + private val ratProfileSettings: RATProfileSettings +) : CWAViewModel() { + + private val profileData = MutableLiveData(RATProfileData()) + val profile: LiveData<RATProfileData?> = profileData + val events = SingleLiveEvent<CreateRATProfileNavigation>() + + fun createProfile() { + val ratProfileData = profileData.value + Timber.d("Profile=%s", ratProfileData) + if (ratProfileData?.isValid == true) { + ratProfileSettings.profile.update { ratProfileData.toRATProfile() } + Timber.d("Profile created") + events.value = CreateRATProfileNavigation.ProfileScreen + } + } + + fun firstNameChanged(firstName: String) { + profileData.apply { + value = value?.copy(firstName = firstName) + } + } + + fun lastNameChanged(lastName: String) { + profileData.apply { + value = value?.copy(lastName = lastName) + } + } + + fun birthDateChanged(birthDate: LocalDate) { + profileData.apply { + value = value?.copy(birthDate = birthDate) + } + } + + fun streetChanged(street: String) { + profileData.apply { + value = value?.copy(street = street) + } + } + + fun zipCodeChanged(zipCode: String) { + profileData.apply { + value = value?.copy(zipCode = zipCode) + } + } + + fun cityChanged(city: String) { + profileData.apply { + value = value?.copy(city = city) + } + } + + fun phoneChanged(phone: String) { + profileData.apply { + value = value?.copy(phone = phone) + } + } + + fun emailChanged(email: String) { + profileData.apply { + value = value?.copy(email = email) + } + } + + fun navigateBack() { + events.value = CreateRATProfileNavigation.Back + } + + @AssistedFactory + interface Factory : SimpleCWAViewModelFactory<RATProfileCreateFragmentViewModel> +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileData.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileData.kt new file mode 100644 index 0000000000000000000000000000000000000000..075f2d373be0f33f16b1c871ff26fa2b224b328d --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileData.kt @@ -0,0 +1,35 @@ +package de.rki.coronawarnapp.ui.coronatest.rat.profile.create + +import de.rki.coronawarnapp.coronatest.antigen.profile.RATProfile +import org.joda.time.LocalDate + +data class RATProfileData( + val firstName: String = "", + val lastName: String = "", + val birthDate: LocalDate? = null, + val street: String = "", + val zipCode: String = "", + val city: String = "", + val phone: String = "", + val email: String = "", +) { + val isValid: Boolean = firstName.isNotBlank() || + lastName.isNotBlank() || + birthDate != null || + street.isNotBlank() || + zipCode.isNotBlank() || + city.isNotBlank() || + phone.isNotBlank() || + email.isNotBlank() +} + +fun RATProfileData.toRATProfile() = RATProfile( + firstName = firstName, + lastName = lastName, + birthDate = birthDate, + street = street, + zipCode = zipCode, + city = city, + phone = phone, + email = email +) diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/onboarding/RATProfileOnboardingFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/onboarding/RATProfileOnboardingFragment.kt new file mode 100644 index 0000000000000000000000000000000000000000..18e46be246132dba85aa54dd3c114c5661320446 --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/onboarding/RATProfileOnboardingFragment.kt @@ -0,0 +1,27 @@ +package de.rki.coronawarnapp.ui.coronatest.rat.profile.onboarding + +import android.os.Bundle +import android.view.View +import androidx.fragment.app.Fragment +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.databinding.RatProfileOnboardingFragmentBinding +import de.rki.coronawarnapp.util.ui.doNavigate +import de.rki.coronawarnapp.util.ui.popBackStack +import de.rki.coronawarnapp.util.ui.viewBindingLazy + +class RATProfileOnboardingFragment : Fragment(R.layout.rat_profile_onboarding_fragment) { + + private val binding: RatProfileOnboardingFragmentBinding by viewBindingLazy() + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) = + with(binding) { + toolbar.setNavigationOnClickListener { popBackStack() } + + nextButton.setOnClickListener { + doNavigate( + RATProfileOnboardingFragmentDirections + .actionRatProfileOnboardingFragmentToRatProfileCreateFragment() + ) + } + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/qrcode/RATProfileQrCodeFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/qrcode/RATProfileQrCodeFragment.kt new file mode 100644 index 0000000000000000000000000000000000000000..4bc5b2120fed99eae14aca2a4a0458e45357461a --- /dev/null +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/qrcode/RATProfileQrCodeFragment.kt @@ -0,0 +1,19 @@ +package de.rki.coronawarnapp.ui.coronatest.rat.profile.qrcode + +import android.os.Bundle +import android.view.View +import androidx.fragment.app.Fragment +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.databinding.RatProfileQrCodeFragmentBinding +import de.rki.coronawarnapp.util.ui.popBackStack +import de.rki.coronawarnapp.util.ui.viewBindingLazy + +class RATProfileQrCodeFragment : Fragment(R.layout.rat_profile_qr_code_fragment) { + + private val binding: RatProfileQrCodeFragmentBinding by viewBindingLazy() + + override fun onViewCreated(view: View, savedInstanceState: Bundle?) { + + binding.closeButton.setOnClickListener { popBackStack() } + } +} diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivityModule.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivityModule.kt index 67297c38309b7a9ab97425d9f93f80926293f8e0..30e1176b6710fb4b85a68de0738a3a18fd41eb14 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivityModule.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/MainActivityModule.kt @@ -8,6 +8,7 @@ import de.rki.coronawarnapp.datadonation.analytics.ui.AnalyticsUIModule import de.rki.coronawarnapp.release.NewReleaseInfoFragment import de.rki.coronawarnapp.release.NewReleaseInfoFragmentModule import de.rki.coronawarnapp.tracing.ui.details.TracingDetailsFragmentModule +import de.rki.coronawarnapp.ui.coronatest.rat.profile.RATProfileUIModule import de.rki.coronawarnapp.ui.presencetracing.PresenceTracingUIModule import de.rki.coronawarnapp.ui.information.InformationFragmentModule import de.rki.coronawarnapp.ui.interoperability.InteroperabilityConfigurationFragment @@ -35,6 +36,7 @@ import de.rki.coronawarnapp.util.viewmodel.CWAViewModelKey NewReleaseInfoFragmentModule::class, AnalyticsUIModule::class, PresenceTracingUIModule::class, + RATProfileUIModule::class, ] ) abstract class MainActivityModule { diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/fragment/SubmissionDispatcherFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/fragment/SubmissionDispatcherFragment.kt index 18b1e1c9ce29c4e5ae593ee333f19450320cccc9..3b16c6f61832089e3e981cf1d006eee4ad428890 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/fragment/SubmissionDispatcherFragment.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/fragment/SubmissionDispatcherFragment.kt @@ -4,6 +4,7 @@ import android.os.Bundle import android.view.View import android.view.accessibility.AccessibilityEvent import androidx.fragment.app.Fragment +import androidx.navigation.NavGraph import androidx.navigation.fragment.findNavController import de.rki.coronawarnapp.R import de.rki.coronawarnapp.databinding.FragmentSubmissionDispatcherBinding @@ -15,6 +16,7 @@ import de.rki.coronawarnapp.util.ui.observe2 import de.rki.coronawarnapp.util.ui.viewBindingLazy import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactoryProvider import de.rki.coronawarnapp.util.viewmodel.cwaViewModels +import timber.log.Timber import javax.inject.Inject class SubmissionDispatcherFragment : Fragment(R.layout.fragment_submission_dispatcher), AutoInject { @@ -46,6 +48,32 @@ class SubmissionDispatcherFragment : Fragment(R.layout.fragment_submission_dispa SubmissionDispatcherFragmentDirections .actionSubmissionDispatcherFragmentToSubmissionConsentFragment() ) + is SubmissionNavigationEvents.NavigateToCreateProfile -> + doNavigate( + SubmissionDispatcherFragmentDirections + .actionSubmissionDispatcherFragmentToRapidTestProfileNavGraph() + ) + + is SubmissionNavigationEvents.NavigateToOpenProfile -> { + val ratGraph = findNavController().graph.findNode(R.id.rapid_test_profile_nav_graph) as NavGraph + ratGraph.startDestination = R.id.ratProfileQrCodeFragment + + doNavigate( + SubmissionDispatcherFragmentDirections + .actionSubmissionDispatcherFragmentToRapidTestProfileNavGraph() + ) + } + } + } + + viewModel.profileCardId.observe(viewLifecycleOwner) { layoutId -> + binding.ratProfileCard.viewStub?.apply { + layoutResource = layoutId + Timber.d("layoutId=$layoutId") + inflate() + binding.ratProfileCard.root.setOnClickListener { + viewModel.onClickProfileCard() + } } } } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/viewmodel/SubmissionDispatcherViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/viewmodel/SubmissionDispatcherViewModel.kt index 4515b7d2c42d1178304fc7900f5ab6e015fed8de..c558190977261129100283f195602654df04c75f 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/viewmodel/SubmissionDispatcherViewModel.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/viewmodel/SubmissionDispatcherViewModel.kt @@ -1,14 +1,32 @@ package de.rki.coronawarnapp.ui.submission.viewmodel +import androidx.lifecycle.LiveData +import androidx.lifecycle.asLiveData import dagger.assisted.AssistedFactory import dagger.assisted.AssistedInject +import de.rki.coronawarnapp.R +import de.rki.coronawarnapp.coronatest.antigen.profile.RATProfileSettings +import de.rki.coronawarnapp.util.coroutine.DispatcherProvider import de.rki.coronawarnapp.util.ui.SingleLiveEvent import de.rki.coronawarnapp.util.viewmodel.CWAViewModel import de.rki.coronawarnapp.util.viewmodel.SimpleCWAViewModelFactory +import kotlinx.coroutines.flow.map +import timber.log.Timber -class SubmissionDispatcherViewModel @AssistedInject constructor() : CWAViewModel() { +class SubmissionDispatcherViewModel @AssistedInject constructor( + private val ratProfileSettings: RATProfileSettings, + dispatcherProvider: DispatcherProvider, +) : CWAViewModel(dispatcherProvider) { val routeToScreen: SingleLiveEvent<SubmissionNavigationEvents> = SingleLiveEvent() + val profileCardId: LiveData<Int> = ratProfileSettings.profile.flow + .map { profile -> + Timber.d("profile=$profile") + if (profile == null) + R.layout.submission_create_rat_profile_card + else + R.layout.submission_open_rat_profile_card + }.asLiveData() fun onBackPressed() { routeToScreen.postValue(SubmissionNavigationEvents.NavigateToMainActivity) @@ -26,6 +44,15 @@ class SubmissionDispatcherViewModel @AssistedInject constructor() : CWAViewModel routeToScreen.postValue(SubmissionNavigationEvents.NavigateToConsent) } + fun onClickProfileCard() { + val event = if (ratProfileSettings.profile.value != null) { + SubmissionNavigationEvents.NavigateToOpenProfile + } else { + SubmissionNavigationEvents.NavigateToCreateProfile + } + routeToScreen.postValue(event) + } + @AssistedFactory interface Factory : SimpleCWAViewModelFactory<SubmissionDispatcherViewModel> } diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/viewmodel/SubmissionNavigationEvents.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/viewmodel/SubmissionNavigationEvents.kt index 1d329dd9ee891610f110da4ccd33cd8338fc81e3..c9efab9912d83ee93da4bdb596965750dee6cbef 100644 --- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/viewmodel/SubmissionNavigationEvents.kt +++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/submission/viewmodel/SubmissionNavigationEvents.kt @@ -23,5 +23,7 @@ sealed class SubmissionNavigationEvents { ) : SubmissionNavigationEvents() data class NavigateToDeletionWarningFragmentFromTan(val coronaTestTan: CoronaTestTAN, val consentGiven: Boolean) : SubmissionNavigationEvents() + object NavigateToCreateProfile : SubmissionNavigationEvents() + object NavigateToOpenProfile : SubmissionNavigationEvents() data class ResolvePlayServicesException(val exception: ApiException) : SubmissionNavigationEvents() } diff --git a/Corona-Warn-App/src/main/res/drawable/blue_card_ripple.xml b/Corona-Warn-App/src/main/res/drawable/blue_card_ripple.xml new file mode 100644 index 0000000000000000000000000000000000000000..c423d6b818a053a732473ece00f77548a16bbade --- /dev/null +++ b/Corona-Warn-App/src/main/res/drawable/blue_card_ripple.xml @@ -0,0 +1,20 @@ +<?xml version="1.0" encoding="utf-8"?> +<ripple xmlns:android="http://schemas.android.com/apk/res/android" + android:color="?android:attr/colorControlHighlight"> + <item android:id="@android:id/mask"> + <shape android:shape="rectangle"> + <solid android:color="@color/colorSurface2Pressed" /> + <corners android:radius="@dimen/radius_card" /> + </shape> + </item> + <item> + + <shape android:shape="rectangle"> + <corners android:radius="@dimen/radius_card" /> + <gradient + android:angle="135" + android:endColor="#599BC4" + android:startColor="#29689B" /> + </shape> + </item> +</ripple> diff --git a/Corona-Warn-App/src/main/res/drawable/ic_rat_profile_create_card_illustration.xml b/Corona-Warn-App/src/main/res/drawable/ic_rat_profile_create_card_illustration.xml new file mode 100644 index 0000000000000000000000000000000000000000..93abfe013c6cca56dab4a9fd183de8eb77b2a347 --- /dev/null +++ b/Corona-Warn-App/src/main/res/drawable/ic_rat_profile_create_card_illustration.xml @@ -0,0 +1,52 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt" + android:width="161dp" + android:height="90dp" + android:viewportWidth="161" + android:viewportHeight="90"> + <path + android:pathData="M0,4C0,1.791 1.791,0 4,0H84C86.209,0 88,1.791 88,4V58C88,60.209 86.209,62 84,62H4C1.791,62 0,60.209 0,58V4Z" + android:fillColor="#C4C4C4"/> + <path + android:pathData="M0,4C0,1.791 1.791,0 4,0H84C86.209,0 88,1.791 88,4V58C88,60.209 86.209,62 84,62H4C1.791,62 0,60.209 0,58V4Z"> + <aapt:attr name="android:fillColor"> + <gradient + android:startY="4.38621E-7" + android:startX="-8.91461" + android:endY="76.41" + android:endX="74.8561" + android:type="linear"> + <item android:offset="0" android:color="#FF599BC4"/> + <item android:offset="1" android:color="#FF29689B"/> + </gradient> + </aapt:attr> + </path> + <path + android:pathData="M42.5,13L74.5,13A3.5,3.5 0,0 1,78 16.5L78,16.5A3.5,3.5 0,0 1,74.5 20L42.5,20A3.5,3.5 0,0 1,39 16.5L39,16.5A3.5,3.5 0,0 1,42.5 13z" + android:fillColor="#ffffff"/> + <path + android:pathData="M43,37L78,37A4,4 0,0 1,82 41L82,48A4,4 0,0 1,78 52L43,52A4,4 0,0 1,39 48L39,41A4,4 0,0 1,43 37z" + android:fillColor="#ffffff" + android:fillAlpha="0.2"/> + <path + android:pathData="M41.5,26L61.5,26A2.5,2.5 0,0 1,64 28.5L64,28.5A2.5,2.5 0,0 1,61.5 31L41.5,31A2.5,2.5 0,0 1,39 28.5L39,28.5A2.5,2.5 0,0 1,41.5 26z" + android:fillColor="#ffffff"/> + <path + android:pathData="M20,23m-12,0a12,12 0,1 1,24 0a12,12 0,1 1,-24 0" + android:fillColor="#ffffff"/> + <group> + <clip-path + android:pathData="M25,20C25,22.75 22.75,25 20,25C17.25,25 15,22.75 15,20C15,17.25 17.25,15 20,15C22.75,15 25,17.25 25,20ZM26.95,28.95C28.8,29.75 30,31.55 30,33.575V35H10V33.575C10,31.55 11.2,29.75 13.05,28.95C15.175,28.025 17.525,27.5 20,27.5C22.475,27.5 24.825,28.025 26.95,28.95Z"/> + <path + android:pathData="M20,23m-12,0a12,12 0,1 1,24 0a12,12 0,1 1,-24 0" + android:fillColor="#C4C4C6"/> + </group> + <path + android:strokeWidth="1" + android:pathData="M75.184,89.565C74.433,89.181 73.819,88.567 73.435,87.816L73.881,87.589C73.637,87.113 73.5,86.573 73.5,86V82.76H73V78.44H73.5V71.96H73V67.64H73.5V61.16H73V56.84H73.5V50.36H73V46.04H73.5V39.56H73V35.24H73.5V32C73.5,31.427 73.637,30.887 73.881,30.411L73.435,30.184C73.819,29.433 74.433,28.819 75.184,28.435L75.411,28.881C75.887,28.637 76.427,28.5 77,28.5H80V28H84V28.5H90V28H94V28.5H100V28H104V28.5H110V28H114V28.5H120V28H124V28.5H130V28H134V28.5H140V28H144V28.5H150V28H154V28.5H157C157.573,28.5 158.113,28.637 158.589,28.881L158.816,28.435C159.567,28.819 160.181,29.433 160.565,30.184L160.119,30.411C160.363,30.887 160.5,31.427 160.5,32V35.24H161V39.56H160.5V46.04H161V50.36H160.5V56.84H161V61.16H160.5V67.64H161V71.96H160.5V78.44H161V82.76H160.5V86C160.5,86.573 160.363,87.113 160.119,87.589L160.565,87.816C160.181,88.567 159.567,89.181 158.816,89.565L158.589,89.119C158.113,89.363 157.573,89.5 157,89.5H154V90H150V89.5H144V90H140V89.5H134V90H130V89.5H124V90H120V89.5H114V90H110V89.5H104V90H100V89.5H94V90H90V89.5H84V90H80V89.5H77C76.427,89.5 75.887,89.363 75.411,89.119L75.184,89.565Z" + android:fillColor="#EAF6FE" + android:strokeColor="#007FAD"/> + <path + android:pathData="M127.333,60.333H119.333V68.333H116.667V60.333H108.667V57.667H116.667V49.667H119.333V57.667H127.333V60.333Z" + android:fillColor="#007FAD"/> +</vector> diff --git a/Corona-Warn-App/src/main/res/drawable/ic_rat_profile_open_card_illustration.xml b/Corona-Warn-App/src/main/res/drawable/ic_rat_profile_open_card_illustration.xml new file mode 100644 index 0000000000000000000000000000000000000000..e4960b9e7be44f32eafdb903a5d7fc881f289e67 --- /dev/null +++ b/Corona-Warn-App/src/main/res/drawable/ic_rat_profile_open_card_illustration.xml @@ -0,0 +1,1187 @@ +<vector xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:aapt="http://schemas.android.com/aapt" + android:width="67dp" + android:height="100dp" + android:viewportWidth="67" + android:viewportHeight="100"> + <group> + <clip-path + android:pathData="M0.386,18.68C-0.378,23.137 10.32,26.962 10.32,26.962L11.212,27.087L11.085,33.711C11.085,33.711 1.025,42.879 1.152,46.446C1.279,50.013 6.879,49.259 6.879,49.259C6.879,49.259 2.382,58.253 4.468,61.089C5.995,63.168 7.908,62.619 7.908,62.619C7.908,62.619 2.832,66.078 4.343,70.006C5.009,71.735 10.2,72.935 10.2,72.935L18.739,73.865C18.435,71.481 18.634,69.125 18.953,66.769L18.94,66.766C19.197,61.67 19.59,56.589 19.686,51.478C19.887,40.839 19.611,30.207 19.549,19.556C14.342,18.124 10.704,17.166 10.704,17.166C10.704,17.166 7.61,16.212 4.802,16.212C2.677,16.212 0.715,16.758 0.386,18.68Z" + android:fillType="evenOdd"/> + <path + android:pathData="M-1.898,11.884L30.057,16.375L21.432,77.751L-10.524,73.26L-1.898,11.884Z" + android:fillColor="#F7B994" + android:fillType="evenOdd"/> + </group> + <group> + <clip-path + android:pathData="M12.286,7.267L12.277,87.518C12.278,90.794 14.918,93.449 18.175,93.451H50.17C53.425,93.451 56.064,90.798 56.066,87.525V7.273C56.064,4.002 53.43,1.35 50.178,1.345L18.184,1.344C14.929,1.344 12.29,3.995 12.286,7.267Z" + android:fillType="evenOdd"/> + <path + android:pathData="M11.064,-7.483L71.431,1.049L57.284,102.279L-3.083,93.748L11.064,-7.483Z" + android:fillColor="#ffffff" + android:fillType="evenOdd"/> + </group> + <path + android:pathData="M12.143,6.953C12.143,4.192 14.381,1.953 17.143,1.953H50.797C53.558,1.953 55.797,4.192 55.797,6.953V36.678H12.143V6.953Z" + android:fillColor="#589AC3"/> + <path + android:pathData="M12.143,6.953C12.143,4.192 14.381,1.953 17.143,1.953H50.797C53.558,1.953 55.797,4.192 55.797,6.953V36.678H12.143V6.953Z"> + <aapt:attr name="android:fillColor"> + <gradient + android:startY="1.953" + android:startX="12.1426" + android:endY="34.9219" + android:endX="57.0853" + android:type="linear"> + <item android:offset="0" android:color="#FF599BC4"/> + <item android:offset="1" android:color="#FF29689B"/> + </gradient> + </aapt:attr> + </path> + <path + android:pathData="M20.213,59.875L47.694,59.875A1,1 0,0 1,48.694 60.875L48.694,65.427A1,1 0,0 1,47.694 66.427L20.213,66.427A1,1 0,0 1,19.213 65.427L19.213,60.875A1,1 0,0 1,20.213 59.875z" + android:fillColor="#599BC4"/> + <path + android:pathData="M17.758,18.473L49.837,18.473A1,1 0,0 1,50.837 19.473L50.837,51.553A1,1 0,0 1,49.837 52.553L17.758,52.553A1,1 0,0 1,16.758 51.553L16.758,19.473A1,1 0,0 1,17.758 18.473z" + android:fillColor="#ffffff"/> + <path + android:pathData="M29.893,22.687H31.008V21.572H29.893V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M33.239,22.687H34.354V21.572H33.239V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M31.008,23.802H32.124V22.687H31.008V23.802Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M34.355,23.802H35.471V22.687H34.355V23.802Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M36.585,23.802H37.7V22.687H36.585V23.802Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M32.124,24.917H33.239V23.802H32.124V24.917Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M36.585,24.917H37.7V23.802H36.585V24.917Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M29.893,26.033H31.008V24.918H29.893V26.033Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M32.124,26.033H33.239V24.918H32.124V26.033Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M34.355,26.033H35.471V24.918H34.355V26.033Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M35.47,26.033H36.585V24.918H35.47V26.033Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M29.893,27.148H31.008V26.033H29.893V27.148Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M31.008,27.148H32.124V26.033H31.008V27.148Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M31.008,28.263H32.124V27.148H31.008V28.263Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M32.124,28.263H33.239V27.148H32.124V28.263Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M35.47,28.263H36.585V27.148H35.47V28.263Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M36.585,28.263H37.7V27.148H36.585V28.263Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M29.893,29.379H31.008V28.264H29.893V29.379Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M33.239,29.379H34.354V28.264H33.239V29.379Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M29.893,30.494H31.008V29.378H29.893V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M31.008,30.494H32.124V29.378H31.008V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M33.239,30.494H34.354V29.378H33.239V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M35.47,30.494H36.585V29.378H35.47V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M36.585,30.494H37.7V29.378H36.585V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M38.816,22.687H39.932V21.572H38.816V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M38.816,23.802H39.932V22.687H38.816V23.802Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M38.816,24.917H39.932V23.802H38.816V24.917Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M41.048,24.917H42.164V23.802H41.048V24.917Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M42.162,24.917H43.277V23.802H42.162V24.917Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M43.278,24.917H44.393V23.802H43.278V24.917Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M44.393,24.917H45.508V23.802H44.393V24.917Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M38.816,26.033H39.932V24.918H38.816V26.033Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M41.048,26.033H42.164V24.918H41.048V26.033Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M42.162,26.033H43.277V24.918H42.162V26.033Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M43.278,26.033H44.393V24.918H43.278V26.033Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M44.393,26.033H45.508V24.918H44.393V26.033Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M38.816,27.148H39.932V26.033H38.816V27.148Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M41.048,27.148H42.164V26.033H41.048V27.148Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M42.162,27.148H43.277V26.033H42.162V27.148Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M43.278,27.148H44.393V26.033H43.278V27.148Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M44.393,27.148H45.508V26.033H44.393V27.148Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M38.816,28.263H39.932V27.148H38.816V28.263Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M41.048,28.263H42.164V27.148H41.048V28.263Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M42.162,28.263H43.277V27.148H42.162V28.263Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M43.278,28.263H44.393V27.148H43.278V28.263Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M44.393,28.263H45.508V27.148H44.393V28.263Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M38.816,29.379H39.932V28.264H38.816V29.379Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M39.932,22.687H41.047V21.572H39.932V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M41.048,22.687H42.164V21.572H41.048V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M42.162,22.687H43.277V21.572H42.162V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M43.278,22.687H44.393V21.572H43.278V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M44.393,22.687H45.508V21.572H44.393V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M45.507,22.687H46.623V21.572H45.507V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M46.625,22.687H47.74V21.572H46.625V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M46.625,23.802H47.74V22.687H46.625V23.802Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M46.625,24.917H47.74V23.802H46.625V24.917Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M46.625,26.033H47.74V24.918H46.625V26.033Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M46.625,27.148H47.74V26.033H46.625V27.148Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M46.625,28.263H47.74V27.148H46.625V28.263Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M46.625,29.379H47.74V28.264H46.625V29.379Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M38.816,30.494H39.932V29.378H38.816V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M39.932,30.494H41.047V29.378H39.932V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M41.048,30.494H42.164V29.378H41.048V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M42.162,30.494H43.277V29.378H42.162V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M43.278,30.494H44.393V29.378H43.278V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M44.393,30.494H45.508V29.378H44.393V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M45.507,30.494H46.623V29.378H45.507V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M46.625,30.494H47.74V29.378H46.625V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,22.687H20.971V21.572H19.855V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M20.97,22.687H22.085V21.572H20.97V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,22.687H23.201V21.572H22.086V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M23.2,22.687H24.316V21.572H23.2V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M24.317,22.687H25.432V21.572H24.317V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M25.432,22.687H26.547V21.572H25.432V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M26.547,22.687H27.663V21.572H26.547V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,22.687H28.778V21.572H27.663V22.687Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,23.802H20.971V22.687H19.855V23.802Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,23.802H28.778V22.687H27.663V23.802Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,24.917H20.971V23.801H19.855V24.917Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,24.917H23.201V23.801H22.086V24.917Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M23.2,24.917H24.316V23.801H23.2V24.917Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M24.317,24.917H25.432V23.802H24.317V24.917Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M25.432,24.917H26.547V23.802H25.432V24.917Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,24.917H28.778V23.802H27.663V24.917Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,26.032H20.971V24.917H19.855V26.032Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,26.032H23.201V24.917H22.086V26.032Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M23.2,26.032H24.316V24.917H23.2V26.032Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M24.317,26.033H25.432V24.918H24.317V26.033Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M25.432,26.033H26.547V24.918H25.432V26.033Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,26.033H28.778V24.918H27.663V26.033Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,27.148H20.971V26.033H19.855V27.148Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,27.148H23.201V26.033H22.086V27.148Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M23.201,27.148H24.316V26.033H23.201V27.148Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M24.317,27.148H25.432V26.033H24.317V27.148Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M25.432,27.148H26.547V26.033H25.432V27.148Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,27.148H28.778V26.033H27.663V27.148Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,28.263H20.971V27.148H19.855V28.263Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,28.263H23.201V27.148H22.086V28.263Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M23.201,28.263H24.316V27.148H23.201V28.263Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M24.317,28.263H25.432V27.148H24.317V28.263Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M25.432,28.263H26.547V27.148H25.432V28.263Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,28.263H28.778V27.148H27.663V28.263Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,29.379H20.971V28.264H19.855V29.379Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,29.379H28.778V28.264H27.663V29.379Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,30.494H20.971V29.378H19.855V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M20.97,30.494H22.085V29.378H20.97V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,30.494H23.201V29.378H22.086V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M23.201,30.494H24.316V29.378H23.201V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M24.317,30.494H25.432V29.378H24.317V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M25.432,30.494H26.547V29.378H25.432V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M26.547,30.494H27.663V29.378H26.547V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,30.494H28.778V29.378H27.663V30.494Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,41.648H20.971V40.533H19.855V41.648Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M20.97,41.648H22.085V40.533H20.97V41.648Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,41.648H23.201V40.533H22.086V41.648Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M23.201,41.648H24.316V40.533H23.201V41.648Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M24.317,41.648H25.432V40.533H24.317V41.648Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M25.432,41.648H26.547V40.533H25.432V41.648Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M26.547,41.648H27.663V40.533H26.547V41.648Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,41.648H28.778V40.533H27.663V41.648Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,42.763H20.971V41.648H19.855V42.763Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,42.763H28.778V41.648H27.663V42.763Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,43.878H20.971V42.764H19.855V43.878Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,43.878H23.201V42.764H22.086V43.878Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M23.201,43.878H24.316V42.764H23.201V43.878Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M24.317,43.878H25.432V42.764H24.317V43.878Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M25.432,43.878H26.547V42.764H25.432V43.878Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,43.878H28.778V42.764H27.663V43.878Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,44.994H20.971V43.879H19.855V44.994Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,44.994H23.201V43.879H22.086V44.994Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M23.201,44.994H24.316V43.879H23.201V44.994Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M24.317,44.994H25.432V43.879H24.317V44.994Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M25.432,44.994H26.547V43.879H25.432V44.994Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,44.994H28.778V43.879H27.663V44.994Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,46.109H20.971V44.994H19.855V46.109Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,46.109H23.201V44.994H22.086V46.109Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M23.201,46.109H24.316V44.994H23.201V46.109Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M24.317,46.109H25.432V44.994H24.317V46.109Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M25.432,46.109H26.547V44.994H25.432V46.109Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,46.109H28.778V44.994H27.663V46.109Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,47.224H20.971V46.109H19.855V47.224Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,47.224H23.201V46.109H22.086V47.224Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M23.201,47.224H24.316V46.109H23.201V47.224Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M24.317,47.224H25.432V46.109H24.317V47.224Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M25.432,47.224H26.547V46.109H25.432V47.224Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,47.224H28.778V46.109H27.663V47.224Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,48.34H20.971V47.225H19.855V48.34Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,48.34H28.778V47.225H27.663V48.34Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,49.455H20.971V48.34H19.855V49.455Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M20.97,49.455H22.085V48.34H20.97V49.455Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,49.455H23.201V48.34H22.086V49.455Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M23.201,49.455H24.316V48.34H23.201V49.455Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M24.317,49.455H25.432V48.34H24.317V49.455Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M25.432,49.455H26.547V48.34H25.432V49.455Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M26.547,49.455H27.663V48.34H26.547V49.455Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,49.455H28.778V48.34H27.663V49.455Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M32.124,31.61H33.239V30.495H32.124V31.61Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M33.239,31.61H34.354V30.495H33.239V31.61Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M34.355,31.61H35.471V30.495H34.355V31.61Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M36.585,31.61H37.7V30.495H36.585V31.61Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,32.725H20.971V31.61H19.855V32.725Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,32.725H23.201V31.61H22.086V32.725Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M23.201,32.725H24.316V31.61H23.201V32.725Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M24.317,32.725H25.432V31.61H24.317V32.725Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M26.547,32.725H27.663V31.61H26.547V32.725Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M29.893,32.725H31.008V31.61H29.893V32.725Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M31.008,32.725H32.124V31.61H31.008V32.725Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M32.124,32.725H33.239V31.61H32.124V32.725Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M34.355,32.725H35.471V31.61H34.355V32.725Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M35.47,32.725H36.585V31.61H35.47V32.725Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M36.585,32.725H37.7V31.61H36.585V32.725Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M37.701,32.725H38.817V31.61H37.701V32.725Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M42.162,32.725H43.277V31.61H42.162V32.725Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M45.507,32.725H46.623V31.61H45.507V32.725Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M46.625,32.725H47.74V31.61H46.625V32.725Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M20.97,33.84H22.085V32.725H20.97V33.84Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M23.201,33.84H24.316V32.725H23.201V33.84Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,33.84H28.778V32.725H27.663V33.84Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M29.893,33.84H31.008V32.725H29.893V33.84Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M34.355,33.84H35.471V32.725H34.355V33.84Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M36.585,33.84H37.7V32.725H36.585V33.84Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M38.816,33.84H39.932V32.725H38.816V33.84Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M42.162,33.84H43.277V32.725H42.162V33.84Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M43.278,33.84H44.393V32.725H43.278V33.84Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M45.507,33.84H46.623V32.725H45.507V33.84Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M19.855,34.956H20.971V33.84H19.855V34.956Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M20.97,34.956H22.085V33.84H20.97V34.956Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,34.956H23.201V33.84H22.086V34.956Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M24.317,34.956H25.432V33.84H24.317V34.956Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M28.778,34.956H29.893V33.84H28.778V34.956Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M31.008,34.956H32.124V33.84H31.008V34.956Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M34.355,34.956H35.471V33.84H34.355V34.956Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M38.816,34.956H39.932V33.84H38.816V34.956Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M41.048,34.956H42.164V33.84H41.048V34.956Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M43.278,34.956H44.393V33.84H43.278V34.956Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,36.07H23.201V34.956H22.086V36.07Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,36.07H28.778V34.956H27.663V36.07Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M28.778,36.07H29.893V34.956H28.778V36.07Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M29.893,36.07H31.008V34.956H29.893V36.07Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M33.239,36.07H34.354V34.956H33.239V36.07Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M35.47,36.07H36.585V34.956H35.47V36.07Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M36.585,36.07H37.7V34.956H36.585V36.07Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M39.932,36.07H41.047V34.956H39.932V36.07Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M41.048,36.07H42.164V34.956H41.048V36.07Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M46.625,36.07H47.74V34.956H46.625V36.07Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M20.97,37.186H22.085V36.071H20.97V37.186Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,37.186H23.201V36.071H22.086V37.186Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M24.317,37.186H25.432V36.071H24.317V37.186Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,37.186H28.778V36.071H27.663V37.186Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M29.893,37.186H31.008V36.071H29.893V37.186Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M31.008,37.186H32.124V36.071H31.008V37.186Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M33.239,37.186H34.354V36.071H33.239V37.186Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M44.393,37.186H45.508V36.071H44.393V37.186Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M45.507,37.186H46.623V36.071H45.507V37.186Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M22.086,38.302H23.201V37.187H22.086V38.302Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M25.432,38.302H26.547V37.187H25.432V38.302Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M26.547,38.302H27.663V37.187H26.547V38.302Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M31.008,38.302H32.124V37.187H31.008V38.302Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M37.701,38.302H38.817V37.187H37.701V38.302Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M39.932,38.302H41.047V37.187H39.932V38.302Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M41.048,38.302H42.164V37.187H41.048V38.302Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M43.278,38.302H44.393V37.187H43.278V38.302Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M20.97,39.417H22.085V38.303H20.97V39.417Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M23.201,39.417H24.316V38.303H23.201V39.417Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M24.317,39.417H25.432V38.303H24.317V39.417Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M27.663,39.417H28.778V38.303H27.663V39.417Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M31.008,39.417H32.124V38.303H31.008V39.417Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M32.124,39.417H33.239V38.303H32.124V39.417Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M34.355,39.417H35.471V38.303H34.355V39.417Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M36.585,39.417H37.7V38.303H36.585V39.417Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M37.701,39.417H38.817V38.303H37.701V39.417Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M42.162,39.417H43.277V38.303H42.162V39.417Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M43.278,39.417H44.393V38.303H43.278V39.417Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M32.124,40.532H33.239V39.417H32.124V40.532Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M34.355,40.532H35.471V39.417H34.355V40.532Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M35.47,40.532H36.585V39.417H35.47V40.532Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M38.816,40.532H39.932V39.417H38.816V40.532Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M39.932,40.532H41.047V39.417H39.932V40.532Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M44.393,40.532H45.508V39.417H44.393V40.532Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M46.625,40.532H47.74V39.417H46.625V40.532Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M29.893,41.648H31.008V40.533H29.893V41.648Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M31.008,41.648H32.124V40.533H31.008V41.648Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M35.47,41.648H36.585V40.533H35.47V41.648Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M36.585,41.648H37.7V40.533H36.585V41.648Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M38.816,41.648H39.932V40.533H38.816V41.648Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M42.162,41.648H43.277V40.533H42.162V41.648Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M44.393,41.648H45.508V40.533H44.393V41.648Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M35.47,42.763H36.585V41.648H35.47V42.763Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M29.893,43.878H31.008V42.764H29.893V43.878Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M31.008,43.878H32.124V42.764H31.008V43.878Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M33.239,43.878H34.354V42.764H33.239V43.878Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M36.585,43.878H37.7V42.764H36.585V43.878Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M37.701,43.878H38.817V42.764H37.701V43.878Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M38.816,43.878H39.932V42.764H38.816V43.878Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M41.048,43.878H42.164V42.764H41.048V43.878Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M44.393,43.878H45.508V42.764H44.393V43.878Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M46.625,43.878H47.74V42.764H46.625V43.878Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M29.893,44.994H31.008V43.879H29.893V44.994Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M34.355,44.994H35.471V43.879H34.355V44.994Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M35.47,44.994H36.585V43.879H35.47V44.994Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M38.816,44.994H39.932V43.879H38.816V44.994Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M31.008,46.109H32.124V44.994H31.008V46.109Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M33.239,46.109H34.354V44.994H33.239V46.109Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M36.585,46.109H37.7V44.994H36.585V46.109Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M37.701,46.109H38.817V44.994H37.701V46.109Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M41.048,46.109H42.164V44.994H41.048V46.109Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M43.278,46.109H44.393V44.994H43.278V46.109Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M39.932,47.224H41.047V46.109H39.932V47.224Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M44.393,47.224H45.508V46.109H44.393V47.224Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M45.507,47.224H46.623V46.109H45.507V47.224Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M46.625,47.224H47.74V46.109H46.625V47.224Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M29.893,48.34H31.008V47.225H29.893V48.34Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M31.008,48.34H32.124V47.225H31.008V48.34Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M33.239,48.34H34.354V47.225H33.239V48.34Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M43.278,48.34H44.393V47.225H43.278V48.34Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M44.393,48.34H45.508V47.225H44.393V48.34Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M32.124,49.455H33.239V48.34H32.124V49.455Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M34.355,49.455H35.471V48.34H34.355V49.455Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M38.816,49.455H39.932V48.34H38.816V49.455Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M46.625,49.455H47.74V48.34H46.625V49.455Z" + android:fillColor="#000000" + android:fillType="evenOdd"/> + <path + android:pathData="M49.882,93.335H17.747C14.476,93.333 11.824,90.681 11.823,87.41L11.832,7.26C11.836,3.992 14.487,1.344 17.756,1.344L49.89,1.345C53.157,1.35 55.802,3.999 55.804,7.265V87.417C55.803,90.686 53.151,93.335 49.882,93.335Z" + android:strokeWidth="2.30564" + android:fillColor="#00000000" + android:fillType="evenOdd" + android:strokeColor="#4A4A4A"/> + <group> + <clip-path + android:pathData="M56.937,29.592C56.937,29.592 57.008,86.048 56.993,86.217C56.587,90.7 56.178,90.406 55.358,91.849C58.817,93.254 72.238,99.389 87.465,106.416C99.587,101.417 108.935,92.778 115.508,80.5L83.152,68.289C83.152,68.289 79.126,66.576 75.744,59.63C72.362,52.685 70.587,36.813 68.002,34.774C68.002,34.774 68.844,21.269 62.143,19.301C62.143,19.301 61.341,9.324 60.602,9.199C60.41,9.168 60.021,9.103 59.519,9.103C58.074,9.103 55.69,9.637 54.367,13.014C52.583,17.567 52.811,26.45 56.937,29.592Z" + android:fillType="evenOdd"/> + <path + android:pathData="M51.922,4.738L127.892,15.415L114.121,113.401L38.15,102.724L51.922,4.738Z" + android:fillColor="#F7B994" + android:fillType="evenOdd"/> + </group> + <path + android:pathData="M61.693,94.59L68.257,98.072V91.236L61.693,94.59Z" + android:fillColor="#F7B994" + android:fillType="evenOdd"/> +</vector> diff --git a/Corona-Warn-App/src/main/res/layout/fragment_submission_dispatcher.xml b/Corona-Warn-App/src/main/res/layout/fragment_submission_dispatcher.xml index c7f1068de61ae287278824a91ba383edf3604e82..4aa5dfa3dc42b20a66e957377f34b82ba15be099 100644 --- a/Corona-Warn-App/src/main/res/layout/fragment_submission_dispatcher.xml +++ b/Corona-Warn-App/src/main/res/layout/fragment_submission_dispatcher.xml @@ -15,8 +15,8 @@ android:id="@+id/submission_dispatcher_header" layout="@layout/include_header" android:layout_width="0dp" - android:focusable="true" android:layout_height="wrap_content" + android:focusable="true" app:icon="@{@drawable/ic_close}" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" @@ -27,10 +27,10 @@ android:id="@+id/submission_dispatcher_scroll" android:layout_width="0dp" android:layout_height="0dp" + app:layout_constraintBottom_toBottomOf="parent" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toBottomOf="@+id/submission_dispatcher_header" - app:layout_constraintBottom_toBottomOf="parent"> + app:layout_constraintTop_toBottomOf="@+id/submission_dispatcher_header"> <androidx.constraintlayout.widget.ConstraintLayout android:layout_width="match_parent" @@ -40,13 +40,13 @@ <ImageView android:id="@+id/submission_dispatcher_illustration" android:layout_width="0dp" + android:layout_height="wrap_content" android:contentDescription="@string/submission_intro_illustration_description" android:focusable="true" - android:layout_height="wrap_content" - app:srcCompat="@drawable/ic_illustration_test" app:layout_constraintEnd_toEndOf="parent" app:layout_constraintStart_toStartOf="parent" - app:layout_constraintTop_toTopOf="parent" /> + app:layout_constraintTop_toTopOf="parent" + app:srcCompat="@drawable/ic_illustration_test" /> <TextView android:id="@+id/submission_dispatcher_text" @@ -55,7 +55,6 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/spacing_normal" android:text="@string/submission_dispatcher_subheadline" - android:focusable="true" app:layout_constraintEnd_toStartOf="@+id/guideline_end" app:layout_constraintStart_toStartOf="@+id/guideline_start" app:layout_constraintTop_toBottomOf="@+id/submission_dispatcher_illustration" /> @@ -67,7 +66,6 @@ android:layout_height="wrap_content" android:layout_marginTop="@dimen/spacing_normal" android:text="@string/submission_dispatcher_needs_testing_subheadline" - android:focusable="true" app:layout_constraintEnd_toStartOf="@+id/guideline_end" app:layout_constraintStart_toStartOf="@+id/guideline_start" app:layout_constraintTop_toBottomOf="@+id/submission_dispatcher_text" /> @@ -87,17 +85,29 @@ app:layout_constraintStart_toStartOf="@+id/guideline_card_start" app:layout_constraintTop_toBottomOf="@+id/submission_dispatcher_needs_testing_text" /> + <!-- Card layout is inflated lazily based on the profile state--> + <ViewStub + android:id="@+id/rat_profile_card" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/guideline_card" + android:layout_marginTop="@dimen/spacing_small" + android:layout_marginEnd="@dimen/guideline_card" + android:inflatedId="@+id/rat_profile_card" + app:layout_constraintEnd_toStartOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/submission_dispatcher_qr" /> + <TextView android:id="@+id/submission_dispatcher_already_positive_text" style="@style/headline6" android:layout_width="0dp" android:layout_height="wrap_content" - android:layout_marginTop="@dimen/spacing_normal" + android:layout_marginTop="@dimen/spacing_medium" android:text="@string/submission_dispatcher_already_positive_subheadline" - android:focusable="true" - app:layout_constraintEnd_toStartOf="@+id/guideline_end" - app:layout_constraintStart_toStartOf="@+id/guideline_start" - app:layout_constraintTop_toBottomOf="@+id/submission_dispatcher_qr" /> + app:layout_constraintEnd_toStartOf="@id/guideline_end" + app:layout_constraintStart_toStartOf="@id/guideline_start" + app:layout_constraintTop_toBottomOf="@id/rat_profile_card" /> <include android:id="@+id/submission_dispatcher_tan_code" diff --git a/Corona-Warn-App/src/main/res/layout/rat_profile_create_fragment.xml b/Corona-Warn-App/src/main/res/layout/rat_profile_create_fragment.xml new file mode 100644 index 0000000000000000000000000000000000000000..46a8837c3ab7ec9e669dd2899897b3f3a9f49302 --- /dev/null +++ b/Corona-Warn-App/src/main/res/layout/rat_profile_create_fragment.xml @@ -0,0 +1,250 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".ui.coronatest.rat.profile.create.RATProfileCreateFragment"> + + <com.google.android.material.appbar.MaterialToolbar + android:id="@+id/toolbar" + style="@style/CWAToolbar.BackArrow" + android:layout_width="0dp" + android:layout_height="wrap_content" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:title="@string/rat_profile_create_title" /> + + <ScrollView + android:id="@+id/scroll_view" + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_marginBottom="24dp" + android:fillViewport="true" + app:layout_constraintBottom_toTopOf="@id/profile_save_button" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/toolbar"> + + <androidx.constraintlayout.widget.ConstraintLayout + android:layout_width="match_parent" + android:layout_height="0dp"> + + <TextView + android:id="@+id/description" + style="@style/body2Medium" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginHorizontal="24dp" + android:layout_marginTop="10dp" + android:text="@string/rat_profile_create_description" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/first_name_input_layout" + style="@style/TextInputLayoutTheme" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginHorizontal="@dimen/spacing_normal" + android:layout_marginTop="@dimen/spacing_small" + android:hint="@string/rat_profile_create_first_name_hint" + app:endIconMode="clear_text" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/description"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/first_name_input_edit" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:focusable="true" + android:imeOptions="actionNext" + android:inputType="textPersonName" /> + + </com.google.android.material.textfield.TextInputLayout> + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/last_name_input_layout" + style="@style/TextInputLayoutTheme" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginHorizontal="@dimen/spacing_normal" + android:layout_marginTop="@dimen/spacing_small" + android:hint="@string/rat_profile_create_last_name_hint" + app:endIconMode="clear_text" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/first_name_input_layout"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/last_name_input_edit" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:focusable="true" + android:imeOptions="actionNext" + android:inputType="textPersonName" /> + + </com.google.android.material.textfield.TextInputLayout> + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/birth_date_input_layout" + style="@style/TextInputLayoutTheme" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginHorizontal="@dimen/spacing_normal" + android:layout_marginTop="@dimen/spacing_small" + android:hint="@string/rat_profile_create_birth_date_hint" + app:endIconMode="clear_text" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/last_name_input_layout"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/birth_date_input_edit" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:clickable="true" + android:cursorVisible="false" + android:focusable="true" + android:focusableInTouchMode="false" + android:imeOptions="actionNext" + android:inputType="date" /> + + </com.google.android.material.textfield.TextInputLayout> + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/street_input_layout" + style="@style/TextInputLayoutTheme" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginHorizontal="@dimen/spacing_normal" + android:layout_marginTop="@dimen/spacing_small" + android:hint="@string/rat_profile_create_street_hint" + app:endIconMode="clear_text" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/birth_date_input_layout"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/street_input_edit" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:focusable="true" + android:imeOptions="actionNext" + android:inputType="text" /> + + </com.google.android.material.textfield.TextInputLayout> + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/zip_code_input_layout" + style="@style/TextInputLayoutTheme" + android:layout_width="100dp" + android:layout_height="wrap_content" + android:layout_marginHorizontal="@dimen/spacing_normal" + android:layout_marginTop="@dimen/spacing_small" + android:hint="@string/rat_profile_create_zip_code_hint" + app:endIconMode="clear_text" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/street_input_layout"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/zip_code_input_edit" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:focusable="true" + android:imeOptions="actionNext" + android:inputType="text" /> + + </com.google.android.material.textfield.TextInputLayout> + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/city_input_layout" + style="@style/TextInputLayoutTheme" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginHorizontal="@dimen/spacing_normal" + android:layout_marginStart="@dimen/spacing_tiny" + android:layout_marginTop="@dimen/spacing_small" + android:layout_marginEnd="@dimen/spacing_normal" + android:hint="@string/rat_profile_create_city_hint" + app:endIconMode="clear_text" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toEndOf="@id/zip_code_input_layout" + app:layout_constraintTop_toBottomOf="@id/street_input_layout"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/city_input_edit" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:focusable="true" + android:imeOptions="actionNext" + android:inputType="text" /> + + </com.google.android.material.textfield.TextInputLayout> + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/phone_input_layout" + style="@style/TextInputLayoutTheme" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginHorizontal="@dimen/spacing_normal" + android:layout_marginTop="@dimen/spacing_small" + android:hint="@string/rat_profile_create_phone_hint" + app:endIconMode="clear_text" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/zip_code_input_layout"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/phone_input_edit" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:focusable="true" + android:imeOptions="actionNext" + android:inputType="phone" /> + + </com.google.android.material.textfield.TextInputLayout> + + <com.google.android.material.textfield.TextInputLayout + android:id="@+id/email_input_layout" + style="@style/TextInputLayoutTheme" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginHorizontal="@dimen/spacing_normal" + android:layout_marginTop="@dimen/spacing_small" + android:hint="@string/rat_profile_create_email_hint" + app:endIconMode="clear_text" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/phone_input_layout"> + + <com.google.android.material.textfield.TextInputEditText + android:id="@+id/email_input_edit" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:focusable="true" + android:imeOptions="actionNext" + android:inputType="textEmailAddress" /> + + </com.google.android.material.textfield.TextInputLayout> + </androidx.constraintlayout.widget.ConstraintLayout> + </ScrollView> + + <Button + android:id="@+id/profile_save_button" + style="@style/buttonPrimary" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginHorizontal="@dimen/spacing_normal" + android:layout_marginTop="@dimen/spacing_small" + android:layout_marginBottom="@dimen/spacing_small" + android:text="@string/rat_profile_create_button" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + tools:enabled="false" /> + +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/layout/rat_profile_onboarding_fragment.xml b/Corona-Warn-App/src/main/res/layout/rat_profile_onboarding_fragment.xml new file mode 100644 index 0000000000000000000000000000000000000000..33891c8dc9f9a4ca984f2dd214336c686a35eb0d --- /dev/null +++ b/Corona-Warn-App/src/main/res/layout/rat_profile_onboarding_fragment.xml @@ -0,0 +1,45 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".ui.coronatest.rat.profile.onboarding.RATProfileOnboardingFragment"> + + <!-- TODO: implement onboarding screen--> + <com.google.android.material.appbar.MaterialToolbar + android:id="@+id/toolbar" + style="@style/CWAToolbar.Close" + android:layout_width="0dp" + android:layout_height="wrap_content" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:title="Schnelltest-Profil" /> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:text="🚧 Onboarding Screen" + android:textSize="40sp" + app:layout_constraintBottom_toTopOf="@+id/nextButton" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintHorizontal_bias="0.5" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <Button + android:id="@+id/nextButton" + style="@style/buttonPrimary" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom|center" + android:layout_marginHorizontal="24dp" + android:layout_marginBottom="24dp" + android:text="Weiter" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" /> + +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/layout/rat_profile_qr_code_fragment.xml b/Corona-Warn-App/src/main/res/layout/rat_profile_qr_code_fragment.xml new file mode 100644 index 0000000000000000000000000000000000000000..b1467f8500be0855d3ac060e51f2163500da632c --- /dev/null +++ b/Corona-Warn-App/src/main/res/layout/rat_profile_qr_code_fragment.xml @@ -0,0 +1,26 @@ +<?xml version="1.0" encoding="utf-8"?> +<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:tools="http://schemas.android.com/tools" + android:layout_width="match_parent" + android:layout_height="match_parent" + tools:context=".ui.coronatest.rat.profile.qrcode.RATProfileQrCodeFragment"> + + <TextView + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_gravity="center" + android:text="🚧 Profile Screen" + android:textSize="40sp" /> + + + <Button + android:id="@+id/closeButton" + style="@style/buttonPrimary" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_gravity="bottom|center" + android:layout_marginHorizontal="24dp" + android:layout_marginBottom="24dp" + android:text="Weiter" /> + +</FrameLayout> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/layout/submission_create_rat_profile_card.xml b/Corona-Warn-App/src/main/res/layout/submission_create_rat_profile_card.xml new file mode 100644 index 0000000000000000000000000000000000000000..0e89fd2eb78ba7e3c99c39c9830f6931ec048fc0 --- /dev/null +++ b/Corona-Warn-App/src/main/res/layout/submission_create_rat_profile_card.xml @@ -0,0 +1,41 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + style="@style/GreyCard.Ripple" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:padding="24dp"> + + <TextView + android:id="@+id/title" + style="@style/headline6" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:text="@string/rat_profile_create_card_title" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <ImageView + android:id="@+id/illustration" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="20dp" + android:importantForAccessibility="no" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/title" + app:srcCompat="@drawable/ic_rat_profile_create_card_illustration" /> + + <TextView + android:id="@+id/subtitle" + style="@style/subtitle" + android:layout_width="match_parent" + android:layout_height="wrap_content" + android:layout_marginTop="18dp" + android:text="@string/rat_profile_create_card_subtitle" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/illustration" /> + +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/layout/submission_open_rat_profile_card.xml b/Corona-Warn-App/src/main/res/layout/submission_open_rat_profile_card.xml new file mode 100644 index 0000000000000000000000000000000000000000..92abe0f97322f2a057ed76ad7bcb30a0743dfc66 --- /dev/null +++ b/Corona-Warn-App/src/main/res/layout/submission_open_rat_profile_card.xml @@ -0,0 +1,61 @@ +<?xml version="1.0" encoding="utf-8"?> +<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + style="@style/BlueCard" + android:layout_width="match_parent" + android:layout_height="wrap_content"> + + <TextView + android:id="@+id/title" + style="@style/headline6" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/spacing_normal" + android:layout_marginTop="@dimen/spacing_normal" + android:layout_marginEnd="@dimen/spacing_small" + android:text="@string/rat_profile_open_card_title" + android:textColor="@android:color/white" + app:layout_constraintEnd_toStartOf="@id/forward_icon" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toTopOf="parent" /> + + <ImageView + android:id="@+id/forward_icon" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/spacing_small" + android:layout_marginEnd="@dimen/spacing_normal" + android:importantForAccessibility="no" + android:src="@drawable/ic_forward" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toTopOf="parent" + app:tint="@color/whiteAlpha60" /> + + <TextView + android:id="@+id/subtitle" + style="@style/subtitle" + android:layout_width="0dp" + android:layout_height="wrap_content" + android:layout_marginStart="@dimen/spacing_normal" + android:layout_marginTop="@dimen/spacing_normal" + android:layout_marginEnd="@dimen/spacing_small" + android:layout_marginBottom="@dimen/spacing_normal" + android:text="@string/rat_profile_open_card_subtitle" + android:textColor="@android:color/white" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toStartOf="@id/illustration" + app:layout_constraintStart_toStartOf="parent" + app:layout_constraintTop_toBottomOf="@id/title" /> + + <ImageView + android:id="@+id/illustration" + android:layout_width="wrap_content" + android:layout_height="wrap_content" + android:layout_marginTop="@dimen/button_icon_margin" + android:importantForAccessibility="no" + app:layout_constraintBottom_toBottomOf="parent" + app:layout_constraintEnd_toEndOf="parent" + app:layout_constraintTop_toBottomOf="@+id/forward_icon" + app:srcCompat="@drawable/ic_rat_profile_open_card_illustration" /> + +</androidx.constraintlayout.widget.ConstraintLayout> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/navigation/nav_graph.xml b/Corona-Warn-App/src/main/res/navigation/nav_graph.xml index bfa756731ac7755907337488500703bb9deb018a..b40d39ed43bae4eee20080f87ccb6de01a19bb59 100644 --- a/Corona-Warn-App/src/main/res/navigation/nav_graph.xml +++ b/Corona-Warn-App/src/main/res/navigation/nav_graph.xml @@ -13,6 +13,9 @@ <include app:graph="@navigation/trace_location_organizer_nav_graph" /> <include app:graph="@navigation/trace_location_attendee_nav_graph" /> + <!-- Rapid antigen test profile graph--> + <include app:graph="@navigation/rapid_antigen_test_profile_nav_graph" /> + <!-- Main --> <fragment android:id="@+id/mainFragment" @@ -261,6 +264,9 @@ <action android:id="@+id/action_submissionDispatcherFragment_to_submissionConsentFragment" app:destination="@id/submissionConsentFragment" /> + <action + android:id="@+id/action_submissionDispatcherFragment_to_rapid_test_profile_nav_graph" + app:destination="@id/rapid_test_profile_nav_graph" /> </fragment> <fragment android:id="@+id/submissionResultPositiveOtherWarningNoConsentFragment" diff --git a/Corona-Warn-App/src/main/res/navigation/rapid_antigen_test_profile_nav_graph.xml b/Corona-Warn-App/src/main/res/navigation/rapid_antigen_test_profile_nav_graph.xml new file mode 100644 index 0000000000000000000000000000000000000000..19f817795d0d7c177388de3a0bbde2b9a918606b --- /dev/null +++ b/Corona-Warn-App/src/main/res/navigation/rapid_antigen_test_profile_nav_graph.xml @@ -0,0 +1,33 @@ +<?xml version="1.0" encoding="utf-8"?> +<navigation xmlns:android="http://schemas.android.com/apk/res/android" + xmlns:app="http://schemas.android.com/apk/res-auto" + xmlns:tools="http://schemas.android.com/tools" + android:id="@+id/rapid_test_profile_nav_graph" + app:startDestination="@id/ratProfileOnboardingFragment"> + + <fragment + android:id="@+id/ratProfileOnboardingFragment" + android:name="de.rki.coronawarnapp.ui.coronatest.rat.profile.onboarding.RATProfileOnboardingFragment" + android:label="rat_profile_onboarding_fragment" + tools:layout="@layout/rat_profile_onboarding_fragment"> + <action + android:id="@+id/action_ratProfileOnboardingFragment_to_ratProfileCreateFragment" + app:destination="@id/ratProfileCreateFragment" /> + </fragment> + <fragment + android:id="@+id/ratProfileCreateFragment" + android:name="de.rki.coronawarnapp.ui.coronatest.rat.profile.create.RATProfileCreateFragment" + android:label="rat_profile_create_fragment" + tools:layout="@layout/rat_profile_create_fragment"> + <action + android:id="@+id/action_ratProfileCreateFragment_to_ratProfileQrCodeFragment" + app:destination="@id/ratProfileQrCodeFragment" + app:popUpTo="@id/rapid_test_profile_nav_graph" + app:popUpToInclusive="true" /> + </fragment> + <fragment + android:id="@+id/ratProfileQrCodeFragment" + android:name="de.rki.coronawarnapp.ui.coronatest.rat.profile.qrcode.RATProfileQrCodeFragment" + android:label="rat_profile_qr_code_fragment" + tools:layout="@layout/rat_profile_qr_code_fragment" /> +</navigation> \ No newline at end of file diff --git a/Corona-Warn-App/src/main/res/values-de/antigen_strings.xml b/Corona-Warn-App/src/main/res/values-de/antigen_strings.xml index 1b2b6aef0f83dacaced41bcbbe0f7a97f1972774..931bbbeb5207900ef9e8fcdedac8e6e47bbdccc1 100644 --- a/Corona-Warn-App/src/main/res/values-de/antigen_strings.xml +++ b/Corona-Warn-App/src/main/res/values-de/antigen_strings.xml @@ -137,4 +137,37 @@ <!-- XTXT: coronatest negative antigen result third info body --> <string name="coronatest_negative_antigen_restul_third_info_body">"Bitte entfernen Sie den Test wieder aus der Corona-Warn-App, damit Sie bei Bedarf einen neuen Test hinterlegen können."</string> + <!-- #################################### + Rapid Antigen Test Profile + ###################################### --> + <!-- XHED: Create RAT profile card title --> + <string name="rat_profile_create_card_title">Schnelltest-Profil anlegen</string> + <!-- XTXT: Create RAT profile card subtitle --> + <string name="rat_profile_create_card_subtitle">Legen Sie ein Profil mit Ihren persönlichen Daten an, die Sie dann per QR-Code bei jedem Schnelltest vorlegen können.</string> + <!-- XHED: Open RAT profile card title --> + <string name="rat_profile_open_card_title">Schnelltest-Profil</string> + <!-- XTXT: Open RAT profile card subtitle --> + <string name="rat_profile_open_card_subtitle">Sparen Sie Zeit und zeigen Sie Ihr Schnelltest-Profil bei der Teststelle vor.</string> + <!-- XHED: Create RAT profile title --> + <string name="rat_profile_create_title">Schnelltest-Profil</string> + <!-- XTXT: Create RAT profile first name hint --> + <string name="rat_profile_create_first_name_hint">Vorname</string> + <!-- XTXT: Create RAT profile last name hint --> + <string name="rat_profile_create_last_name_hint">Nachname</string> + <!-- XTXT: Create RAT profile birth date hint --> + <string name="rat_profile_create_birth_date_hint">Geburtsdatum</string> + <!-- XBUT: Create RAT profile save button --> + <string name="rat_profile_create_button">Specihern</string> + <!-- XTXT: Create RAT profile description --> + <string name="rat_profile_create_description">Legen Sie Ihre persönlichen Daten als QR-Code ab, um die Registrierung an der Teststelle zu beschleunigen.</string> + <!-- XTXT: Create RAT profile street hint --> + <string name="rat_profile_create_street_hint">Straße und Hausnummer</string> + <!-- XTXT: Create RAT profile post code hint --> + <string name="rat_profile_create_zip_code_hint">PLZ</string> + <!-- XTXT: Create RAT profile city hint --> + <string name="rat_profile_create_city_hint">Stadt</string> + <!-- XTXT: Create RAT profile phone hint --> + <string name="rat_profile_create_phone_hint">Telefonnummer</string> + <!-- XTXT: Create RAT profile email hint --> + <string name="rat_profile_create_email_hint">E-Mail-Adresse</string> </resources> diff --git a/Corona-Warn-App/src/main/res/values/antigen_strings.xml b/Corona-Warn-App/src/main/res/values/antigen_strings.xml index 85dd938a6c8a09b37c935a2b5d90bcba08d8078c..f1cdaff71116b98a198ee65e077e62a1906d394a 100644 --- a/Corona-Warn-App/src/main/res/values/antigen_strings.xml +++ b/Corona-Warn-App/src/main/res/values/antigen_strings.xml @@ -137,4 +137,37 @@ <!-- XTXT: coronatest negative antigen result third info body --> <string name="coronatest_negative_antigen_restul_third_info_body">"Bitte entfernen Sie den Test wieder aus der Corona-Warn-App, damit Sie bei Bedarf einen neuen Test hinterlegen können."</string> + <!-- #################################### + Rapid Antigen Test Profile + ###################################### --> + <!-- XHED: Create RAT profile card title --> + <string name="rat_profile_create_card_title">Schnelltest-Profil anlegen</string> + <!-- XTXT: Create RAT profile card subtitle --> + <string name="rat_profile_create_card_subtitle">Legen Sie ein Profil mit Ihren persönlichen Daten an, die Sie dann per QR-Code bei jedem Schnelltest vorlegen können.</string> + <!-- XHED: Open RAT profile card title --> + <string name="rat_profile_open_card_title">Schnelltest-Profil</string> + <!-- XTXT: Open RAT profile card subtitle --> + <string name="rat_profile_open_card_subtitle">Sparen Sie Zeit und zeigen Sie Ihr Schnelltest-Profil bei der Teststelle vor.</string> + <!-- XHED: Create RAT profile title --> + <string name="rat_profile_create_title">Schnelltest-Profil</string> + <!-- XTXT: Create RAT profile first name hint --> + <string name="rat_profile_create_first_name_hint">Vorname</string> + <!-- XTXT: Create RAT profile last name hint --> + <string name="rat_profile_create_last_name_hint">Nachname</string> + <!-- XTXT: Create RAT profile birth date hint --> + <string name="rat_profile_create_birth_date_hint">Geburtsdatum</string> + <!-- XBUT: Create RAT profile save button --> + <string name="rat_profile_create_button">Specihern</string> + <!-- XTXT: Create RAT profile description --> + <string name="rat_profile_create_description">Legen Sie Ihre persönlichen Daten als QR-Code ab, um die Registrierung an der Teststelle zu beschleunigen.</string> + <!-- XTXT: Create RAT profile street hint --> + <string name="rat_profile_create_street_hint">Straße und Hausnummer</string> + <!-- XTXT: Create RAT profile post code hint --> + <string name="rat_profile_create_zip_code_hint">PLZ</string> + <!-- XTXT: Create RAT profile city hint --> + <string name="rat_profile_create_city_hint">Stadt</string> + <!-- XTXT: Create RAT profile phone hint --> + <string name="rat_profile_create_phone_hint">Telefonnummer</string> + <!-- XTXT: Create RAT profile email hint --> + <string name="rat_profile_create_email_hint">E-Mail-Adresse</string> </resources> diff --git a/Corona-Warn-App/src/main/res/values/colors.xml b/Corona-Warn-App/src/main/res/values/colors.xml index 566b2ecaf1aa5b0f3135e86cf32a5f616039ed7b..b7063323ae1e42e5116b21d203e7f41824ac4718 100644 --- a/Corona-Warn-App/src/main/res/values/colors.xml +++ b/Corona-Warn-App/src/main/res/values/colors.xml @@ -104,4 +104,6 @@ <!-- Swipe to delete background color --> <color name="swipeDeleteBackgroundColor">#EB4D3D</color> + + <color name="whiteAlpha60">#99FFFFFF</color> </resources> diff --git a/Corona-Warn-App/src/main/res/values/styles.xml b/Corona-Warn-App/src/main/res/values/styles.xml index 83fb7087b9c6515e8c37a04b8099c88c9ba08cc3..f8c051894a0b6af393e988d086a2dde72b5382dd 100644 --- a/Corona-Warn-App/src/main/res/values/styles.xml +++ b/Corona-Warn-App/src/main/res/values/styles.xml @@ -235,6 +235,10 @@ <item name="android:background">@drawable/grey_card_ripple</item> </style> + <style name="BlueCard"> + <item name="android:background">@drawable/blue_card_ripple</item> + </style> + <style name="cardTracing"> <item name="android:padding">@dimen/card_padding</item> <item name="android:background">@drawable/card</item> diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/antigen/profile/RATProfileSettingsTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/antigen/profile/RATProfileSettingsTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..c7fc26a87f5ab86525473dbf43843fc867055376 --- /dev/null +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/coronatest/antigen/profile/RATProfileSettingsTest.kt @@ -0,0 +1,101 @@ +package de.rki.coronawarnapp.coronatest.antigen.profile + +import android.content.Context +import de.rki.coronawarnapp.util.serialization.SerializationModule +import io.kotest.matchers.shouldBe +import io.mockk.MockKAnnotations +import io.mockk.every +import io.mockk.impl.annotations.MockK +import org.joda.time.format.DateTimeFormat +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.BeforeEach +import testhelpers.BaseTest +import testhelpers.extensions.toComparableJsonPretty +import testhelpers.preferences.MockSharedPreferences + +internal class RATProfileSettingsTest : BaseTest() { + @MockK lateinit var context: Context + private val mockPreferences = MockSharedPreferences() + private lateinit var ratProfileSettings: RATProfileSettings + private val formatter = DateTimeFormat.forPattern("yyyy-MM-dd") + private val profile = RATProfile( + firstName = "First name", + lastName = "Last name", + birthDate = formatter.parseLocalDate("1950-08-01"), + street = "Main street", + zipCode = "12132", + city = "London", + phone = "111111111", + email = "email@example.com" + ) + + @BeforeEach + fun setup() { + MockKAnnotations.init(this) + + every { + context.getSharedPreferences("ratprofile_localdata", Context.MODE_PRIVATE) + } returns mockPreferences + + ratProfileSettings = RATProfileSettings( + context, + SerializationModule().baseGson() + ) + } + + @Test + fun `Profile has birth date`() { + ratProfileSettings.profile.update { profile } + val json = (mockPreferences.dataMapPeek["ratprofile.settings.profile"] as String) + json.toComparableJsonPretty() shouldBe + """ + { + "firstName": "First name", + "lastName": "Last name", + "birthDate": "1950-08-01", + "street": "Main street", + "zipCode": "12132", + "city": "London", + "phone": "111111111", + "email": "email@example.com" + } + """.trimIndent() + } + + @Test + fun `Profile hasn't birth date`() { + ratProfileSettings.profile.update { profile.copy(birthDate = null) } + val json = (mockPreferences.dataMapPeek["ratprofile.settings.profile"] as String) + json.toComparableJsonPretty() shouldBe + """ + { + "firstName": "First name", + "lastName": "Last name", + "street": "Main street", + "zipCode": "12132", + "city": "London", + "phone": "111111111", + "email": "email@example.com" + } + """.trimIndent() + } + + @Test + fun `Profile has empty properties`() { + ratProfileSettings.profile.update { profile.copy(firstName = "", lastName = "") } + val json = (mockPreferences.dataMapPeek["ratprofile.settings.profile"] as String) + json.toComparableJsonPretty() shouldBe + """ + { + "firstName": "", + "lastName": "", + "birthDate": "1950-08-01", + "street": "Main street", + "zipCode": "12132", + "city": "London", + "phone": "111111111", + "email": "email@example.com" + } + """.trimIndent() + } +} diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileDataCreateFragmentViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileDataCreateFragmentViewModelTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..14e222cb2fd820ef48f5c2d95ce9019944cc3686 --- /dev/null +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileDataCreateFragmentViewModelTest.kt @@ -0,0 +1,181 @@ +package de.rki.coronawarnapp.ui.coronatest.rat.profile.create + +import de.rki.coronawarnapp.coronatest.antigen.profile.RATProfileSettings +import io.kotest.matchers.shouldBe +import io.mockk.MockKAnnotations +import io.mockk.every +import io.mockk.impl.annotations.MockK +import io.mockk.verify +import org.joda.time.format.DateTimeFormat +import org.junit.jupiter.api.Test +import org.junit.jupiter.api.BeforeEach +import org.junit.jupiter.api.extension.ExtendWith +import testhelpers.BaseTest +import testhelpers.extensions.InstantExecutorExtension +import testhelpers.extensions.getOrAwaitValue +import testhelpers.preferences.mockFlowPreference + +@ExtendWith(InstantExecutorExtension::class) +internal class RATProfileDataCreateFragmentViewModelTest : BaseTest() { + + @MockK lateinit var ratProfileSettings: RATProfileSettings + + private val formatter = DateTimeFormat.forPattern("dd.MM.yyyy") + + @BeforeEach + fun setup() { + MockKAnnotations.init(this) + every { ratProfileSettings.profile } returns mockFlowPreference(null) + } + + @Test + fun `createProfile nothing is set does not create profile`() { + viewModel().apply { + createProfile() + } + + verify(exactly = 0) { + ratProfileSettings.profile + } + } + + @Test + fun `createProfile create profile when at least one field is set`() { + viewModel().apply { + firstNameChanged("First name") + createProfile() + events.getOrAwaitValue() shouldBe CreateRATProfileNavigation.ProfileScreen + } + + verify { + ratProfileSettings.profile + } + } + + @Test + fun firstNameChanged() { + viewModel().apply { + firstNameChanged("First name") + profile.getOrAwaitValue()!!.apply { + firstName shouldBe "First name" + isValid shouldBe true + } + } + } + + @Test + fun lastNameChanged() { + viewModel().apply { + lastNameChanged("Last name") + profile.getOrAwaitValue()!!.apply { + lastName shouldBe "Last name" + isValid shouldBe true + } + } + } + + @Test + fun birthDateChanged() { + val birthDate = formatter.parseLocalDate("01.01.2021") + viewModel().apply { + birthDateChanged(birthDate) + profile.getOrAwaitValue()!!.apply { + birthDate shouldBe birthDate + isValid shouldBe true + } + } + } + + @Test + fun streetChanged() { + viewModel().apply { + streetChanged("Main St.") + profile.getOrAwaitValue()!!.apply { + street shouldBe "Main St." + isValid shouldBe true + } + } + } + + @Test + fun zipCodeChanged() { + viewModel().apply { + zipCodeChanged("11111") + profile.getOrAwaitValue()!!.apply { + zipCode shouldBe "11111" + isValid shouldBe true + } + } + } + + @Test + fun cityChanged() { + viewModel().apply { + cityChanged("London") + profile.getOrAwaitValue()!!.apply { + city shouldBe "London" + isValid shouldBe true + } + } + } + + @Test + fun phoneChanged() { + viewModel().apply { + phoneChanged("111111111") + profile.getOrAwaitValue()!!.apply { + phone shouldBe "111111111" + isValid shouldBe true + } + } + } + + @Test + fun emailChanged() { + viewModel().apply { + emailChanged("email@example.com") + profile.getOrAwaitValue()!!.apply { + email shouldBe "email@example.com" + isValid shouldBe true + } + } + } + + @Test + fun allFieldsAreSet() { + val birthDate = formatter.parseDateTime("01.01.1980").toLocalDate() + viewModel().apply { + firstNameChanged("First name") + lastNameChanged("Last name") + birthDateChanged(birthDate) + streetChanged("Main street") + zipCodeChanged("12132") + cityChanged("London") + phoneChanged("111111111") + emailChanged("email@example.com") + profile.getOrAwaitValue()!!.apply { + isValid shouldBe true + this shouldBe RATProfileData( + firstName = "First name", + lastName = "Last name", + birthDate = birthDate, + street = "Main street", + zipCode = "12132", + city = "London", + phone = "111111111", + email = "email@example.com" + ) + } + } + } + + @Test + fun navigateBack() { + viewModel().apply { + navigateBack() + events.getOrAwaitValue() shouldBe CreateRATProfileNavigation.Back + } + } + + fun viewModel() = RATProfileCreateFragmentViewModel(ratProfileSettings) +} diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileDataKtTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileDataKtTest.kt new file mode 100644 index 0000000000000000000000000000000000000000..87be970d8ed25701c35f2b57384cecfb1d569b33 --- /dev/null +++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/ui/coronatest/rat/profile/create/RATProfileDataKtTest.kt @@ -0,0 +1,52 @@ +package de.rki.coronawarnapp.ui.coronatest.rat.profile.create + +import de.rki.coronawarnapp.coronatest.antigen.profile.RATProfile +import io.kotest.matchers.shouldBe +import org.joda.time.format.DateTimeFormat +import org.junit.jupiter.api.Test +import testhelpers.BaseTest + +class RATProfileDataKtTest : BaseTest() { + private val formatter = DateTimeFormat.forPattern("dd.MM.yyyy") + + private val ratProfileData = RATProfileData( + firstName = "First name", + lastName = "Last name", + birthDate = null, + street = "Main street", + zipCode = "12132", + city = "London", + phone = "111111111", + email = "email@example.com" + ) + + @Test + fun `Map ratProfileData - birthDate is missing `() { + ratProfileData.toRATProfile() shouldBe RATProfile( + firstName = "First name", + lastName = "Last name", + birthDate = null, + street = "Main street", + zipCode = "12132", + city = "London", + phone = "111111111", + email = "email@example.com" + ) + } + + @Test + fun `Map ratProfileData - birthDate exists`() { + val birthDate = formatter.parseDateTime("01.01.1980").toLocalDate() + ratProfileData.copy(birthDate = birthDate).toRATProfile() shouldBe + RATProfile( + firstName = "First name", + lastName = "Last name", + birthDate = birthDate, + street = "Main street", + zipCode = "12132", + city = "London", + phone = "111111111", + email = "email@example.com" + ) + } +}