diff --git a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentTest.kt b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentTest.kt
index 03430513efd136f91f631d65df8dfbd2df483029..3099ffa1e939354cbfe2df416caf144abf34fbfb 100644
--- a/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentTest.kt
+++ b/Corona-Warn-App/src/androidTest/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentTest.kt
@@ -92,7 +92,7 @@ class HomeFragmentTest : BaseUITest() {
             every { tracingHeaderState } returns MutableLiveData(TracingHeaderState.TracingActive)
             every { showLoweredRiskLevelDialog } returns MutableLiveData()
             every { homeItems } returns homeFragmentItemsLiveData()
-            every { popupEvents } returns SingleLiveEvent()
+            every { events } returns SingleLiveEvent()
             every { showPopUps() } just Runs
             every { restoreAppShortcuts() } just Runs
         }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt
index 86ed99b07f2de4307fd264362a46bbd4c5800ad3..beb511eae8d709ac0fb8ab3f2938559fc1c9d06d 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragment.kt
@@ -5,7 +5,6 @@ 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 androidx.navigation.ui.onNavDestinationSelected
 import androidx.recyclerview.widget.DefaultItemAnimator
@@ -25,6 +24,7 @@ import de.rki.coronawarnapp.util.errors.RecoveryByResetDialogFactory
 import de.rki.coronawarnapp.util.lists.decorations.TopBottomPaddingDecorator
 import de.rki.coronawarnapp.util.lists.diffutil.update
 import de.rki.coronawarnapp.util.ui.doNavigate
+import de.rki.coronawarnapp.util.ui.findNestedGraph
 import de.rki.coronawarnapp.util.ui.observe2
 import de.rki.coronawarnapp.util.ui.viewBinding
 import de.rki.coronawarnapp.util.viewmodel.CWAViewModelFactoryProvider
@@ -40,30 +40,23 @@ import javax.inject.Inject
 class HomeFragment : Fragment(R.layout.home_fragment_layout), AutoInject {
 
     @Inject lateinit var viewModelFactory: CWAViewModelFactoryProvider.Factory
-    private val viewModel: HomeFragmentViewModel by cwaViewModels(
+    @Inject lateinit var tracingExplanationDialog: TracingExplanationDialog
+    @Inject lateinit var deviceTimeIncorrectDialog: DeviceTimeIncorrectDialog
+
+    private val viewModel by cwaViewModels<HomeFragmentViewModel>(
         ownerProducer = { requireActivity().viewModelStore },
         factoryProducer = { viewModelFactory }
     )
 
-    val binding: HomeFragmentLayoutBinding by viewBinding()
-
-    @Inject lateinit var tracingExplanationDialog: TracingExplanationDialog
-    @Inject lateinit var deviceTimeIncorrectDialog: DeviceTimeIncorrectDialog
-
+    private val binding by viewBinding<HomeFragmentLayoutBinding>()
     private val homeAdapter = HomeAdapter()
 
     override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
-        super.onViewCreated(view, savedInstanceState)
-
         with(binding.toolbar) {
             menu.findItem(R.id.test_nav_graph).isVisible = CWADebug.isDeviceForTestersBuild
             setOnMenuItemClickListener { it.onNavDestinationSelected(findNavController()) }
         }
 
-        viewModel.tracingHeaderState.observe2(this) {
-            binding.tracingHeader = it
-        }
-
         binding.recyclerView.apply {
             layoutManager = LinearLayoutManager(requireContext())
             itemAnimator = DefaultItemAnimator()
@@ -71,84 +64,19 @@ class HomeFragment : Fragment(R.layout.home_fragment_layout), AutoInject {
             adapter = homeAdapter
         }
 
-        viewModel.homeItems.observe2(this) {
-            homeAdapter.update(it)
-        }
-
-        viewModel.routeToScreen.observe2(this) {
-            doNavigate(it)
-        }
-
         binding.mainTracing.setOnClickListener {
             doNavigate(HomeFragmentDirections.actionMainFragmentToSettingsTracingFragment())
         }
 
-        viewModel.openFAQUrlEvent.observe2(this) {
-            openUrl(getString(R.string.main_about_link))
-        }
-
-        viewModel.openIncompatibleEvent.observe2(this) {
-            openUrl(
-                getString(
-                    when (it) { // true if scanning is supported
-                        true -> R.string.incompatible_link_advertising_not_supported
-                        else -> R.string.incompatible_link_scanning_not_supported
-                    }
-                )
-            )
-        }
-
-        viewModel.openTraceLocationOrganizerFlow.observe2(this) {
-            if (viewModel.wasQRInfoWasAcknowledged()) {
-                val nestedGraph =
-                    findNavController().graph.findNode(R.id.trace_location_organizer_nav_graph) as NavGraph
-                nestedGraph.startDestination = R.id.traceLocationsFragment
-            }
-            doNavigate(HomeFragmentDirections.actionMainFragmentToTraceLocationOrganizerNavGraph())
-        }
-
-        viewModel.openVaccinationRegistrationFlow.observe2(this) {
-            if (viewModel.wasVaccinationRegistrationAcknowledged()) {
-                val nestedGraph =
-                    findNavController().graph.findNode(R.id.vaccination_nav_graph) as NavGraph
-                nestedGraph.startDestination = R.id.vaccinationQrCodeScanFragment
-            }
-            doNavigate(HomeFragmentDirections.actionMainFragmentToVaccinationNavGraph())
-        }
-
-        viewModel.popupEvents.observe2(this) { event ->
-            when (event) {
-                HomeFragmentEvents.ShowErrorResetDialog -> {
-                    RecoveryByResetDialogFactory(this).showDialog(
-                        detailsLink = R.string.errors_generic_text_catastrophic_error_encryption_failure,
-                        onPositive = { viewModel.errorResetDialogDismissed() }
-                    )
-                }
-                is HomeFragmentEvents.ShowDeleteTestDialog -> showRemoveTestDialog(event.type)
-                HomeFragmentEvents.GoToStatisticsExplanation -> doNavigate(
-                    HomeFragmentDirections.actionMainFragmentToStatisticsExplanationFragment()
-                )
-                HomeFragmentEvents.ShowTracingExplanation -> {
-                    tracingExplanationDialog.show {
-                        viewModel.tracingExplanationWasShown()
-                    }
-                }
-                is HomeFragmentEvents.GoToVaccinationList -> findNavController().navigate(
-                    VaccinationListFragment.navigationUri(event.personIdentifierCodeSha256)
-                )
-            }
-        }
-
         viewModel.showPopUps()
-
-        viewModel.showLoweredRiskLevelDialog.observe2(this) {
-            if (it) showRiskLevelLoweredDialog()
-        }
+        viewModel.events.observe2(this) { event -> event?.let { navigate(event) } }
+        viewModel.homeItems.observe2(this) { homeAdapter.update(it) }
+        viewModel.errorEvent.observe2(this) { it.toErrorDialogBuilder(requireContext()).show() }
+        viewModel.tracingHeaderState.observe2(this) { binding.tracingHeader = it }
+        viewModel.showLoweredRiskLevelDialog.observe2(this) { if (it) showRiskLevelLoweredDialog() }
         viewModel.showIncorrectDeviceTimeDialog.observe2(this) { showDialog ->
-            if (!showDialog) return@observe2
-            deviceTimeIncorrectDialog.show { viewModel.userHasAcknowledgedIncorrectDeviceTime() }
+            if (showDialog) deviceTimeIncorrectDialog.show { viewModel.userHasAcknowledgedIncorrectDeviceTime() }
         }
-
         viewModel.coronaTestErrors.observe2(this) { tests ->
             tests.forEach { test ->
                 test.lastError?.toErrorDialogBuilder(requireContext())?.apply {
@@ -160,10 +88,6 @@ class HomeFragment : Fragment(R.layout.home_fragment_layout), AutoInject {
                 }?.show()
             }
         }
-
-        viewModel.errorEvent.observe2(this) {
-            it.toErrorDialogBuilder(requireContext()).show()
-        }
     }
 
     override fun onResume() {
@@ -205,4 +129,75 @@ class HomeFragment : Fragment(R.layout.home_fragment_layout), AutoInject {
             getButton(DialogInterface.BUTTON_POSITIVE).setTextColor(context.getColorCompat(R.color.colorTextTint))
         }
     }
+
+    private fun navigate(event: HomeFragmentEvents) {
+        when (event) {
+            HomeFragmentEvents.ShowErrorResetDialog -> {
+                RecoveryByResetDialogFactory(this).showDialog(
+                    detailsLink = R.string.errors_generic_text_catastrophic_error_encryption_failure,
+                    onPositive = { viewModel.errorResetDialogDismissed() }
+                )
+            }
+            HomeFragmentEvents.GoToStatisticsExplanation -> doNavigate(
+                HomeFragmentDirections.actionMainFragmentToStatisticsExplanationFragment()
+            )
+            HomeFragmentEvents.ShowTracingExplanation -> tracingExplanationDialog.show {
+                viewModel.tracingExplanationWasShown()
+            }
+            HomeFragmentEvents.GoToRiskDetailsFragment -> doNavigate(
+                HomeFragmentDirections.actionMainFragmentToRiskDetailsFragment()
+            )
+            HomeFragmentEvents.GoToSettingsTracingFragment -> doNavigate(
+                HomeFragmentDirections.actionMainFragmentToSettingsTracingFragment()
+            )
+            HomeFragmentEvents.GoToSubmissionDispatcher -> doNavigate(
+                HomeFragmentDirections.actionMainFragmentToSubmissionDispatcher()
+            )
+            HomeFragmentEvents.OpenFAQUrl -> openUrl(getString(R.string.main_about_link))
+            HomeFragmentEvents.GoToRapidTestResultNegativeFragment -> doNavigate(
+                HomeFragmentDirections.actionMainFragmentToSubmissionNegativeAntigenTestResultFragment()
+            )
+            is HomeFragmentEvents.ShowDeleteTestDialog -> showRemoveTestDialog(event.type)
+            is HomeFragmentEvents.OpenIncompatibleUrl -> openUrl(getString(event.url))
+            is HomeFragmentEvents.OpenVaccinationRegistrationGraph -> openVaccinationGraph(event)
+            is HomeFragmentEvents.OpenTraceLocationOrganizerGraph -> openPresenceTracingOrganizerGraph(event)
+            is HomeFragmentEvents.GoToTestResultAvailableFragment -> doNavigate(
+                HomeFragmentDirections.actionMainFragmentToSubmissionTestResultAvailableFragment(event.type)
+            )
+            is HomeFragmentEvents.GoToPcrTestResultNegativeFragment -> doNavigate(
+                HomeFragmentDirections.actionMainFragmentToSubmissionTestResultNegativeFragment(event.type)
+            )
+            is HomeFragmentEvents.GoToTestResultKeysSharedFragment -> doNavigate(
+                HomeFragmentDirections.actionMainFragmentToSubmissionTestResultKeysSharedFragment(event.type)
+            )
+            is HomeFragmentEvents.GoToVaccinationList -> findNavController().navigate(
+                VaccinationListFragment.navigationUri(event.personIdentifierCodeSha256)
+            )
+            is HomeFragmentEvents.GoToTestResultPositiveFragment -> doNavigate(
+                HomeFragmentDirections.actionMainFragmentToSubmissionResultPositiveOtherWarningNoConsentFragment(
+                    event.type
+                )
+            )
+            is HomeFragmentEvents.GoToTestResultPendingFragment -> doNavigate(
+                HomeFragmentDirections.actionMainFragmentToSubmissionTestResultPendingFragment(
+                    event.testType,
+                    event.forceUpdate
+                )
+            )
+        }
+    }
+
+    private fun openPresenceTracingOrganizerGraph(event: HomeFragmentEvents.OpenTraceLocationOrganizerGraph) {
+        if (event.qrInfoAcknowledged) {
+            findNestedGraph(R.id.trace_location_organizer_nav_graph).startDestination = R.id.traceLocationsFragment
+        }
+        doNavigate(HomeFragmentDirections.actionMainFragmentToTraceLocationOrganizerNavGraph())
+    }
+
+    private fun openVaccinationGraph(event: HomeFragmentEvents.OpenVaccinationRegistrationGraph) {
+        if (event.registrationAcknowledged) {
+            findNestedGraph(R.id.vaccination_nav_graph).startDestination = R.id.vaccinationQrCodeScanFragment
+        }
+        doNavigate(HomeFragmentDirections.actionMainFragmentToVaccinationNavGraph())
+    }
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentEvents.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentEvents.kt
index 52e8e337966a600284fc84ae41a082e069ee3d8f..e458063333eb10098fc6997f12cba13d176d54d5 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentEvents.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentEvents.kt
@@ -1,5 +1,7 @@
 package de.rki.coronawarnapp.ui.main.home
 
+import androidx.annotation.StringRes
+import de.rki.coronawarnapp.R
 import de.rki.coronawarnapp.coronatest.type.CoronaTest
 
 sealed class HomeFragmentEvents {
@@ -10,7 +12,43 @@ sealed class HomeFragmentEvents {
 
     object GoToStatisticsExplanation : HomeFragmentEvents()
 
+    object GoToRiskDetailsFragment : HomeFragmentEvents()
+
+    object GoToSettingsTracingFragment : HomeFragmentEvents()
+
+    object GoToSubmissionDispatcher : HomeFragmentEvents()
+
+    object OpenFAQUrl : HomeFragmentEvents()
+
+    object GoToRapidTestResultNegativeFragment : HomeFragmentEvents()
+
+    data class GoToPcrTestResultNegativeFragment(val type: CoronaTest.Type) : HomeFragmentEvents()
+
+    data class GoToTestResultKeysSharedFragment(val type: CoronaTest.Type) : HomeFragmentEvents()
+
+    data class OpenIncompatibleUrl(val scanningSupported: Boolean) : HomeFragmentEvents() {
+        @get:StringRes
+        val url: Int
+            get() = when {
+                scanningSupported -> R.string.incompatible_link_advertising_not_supported
+                else -> R.string.incompatible_link_scanning_not_supported
+            }
+    }
+
+    data class OpenVaccinationRegistrationGraph(val registrationAcknowledged: Boolean) : HomeFragmentEvents()
+
+    data class OpenTraceLocationOrganizerGraph(val qrInfoAcknowledged: Boolean) : HomeFragmentEvents()
+
+    data class GoToTestResultPendingFragment(
+        val testType: CoronaTest.Type,
+        val forceUpdate: Boolean = false
+    ) : HomeFragmentEvents()
+
     data class ShowDeleteTestDialog(val type: CoronaTest.Type) : HomeFragmentEvents()
 
+    data class GoToTestResultAvailableFragment(val type: CoronaTest.Type) : HomeFragmentEvents()
+
+    data class GoToTestResultPositiveFragment(val type: CoronaTest.Type) : HomeFragmentEvents()
+
     data class GoToVaccinationList(val personIdentifierCodeSha256: String) : HomeFragmentEvents()
 }
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt
index 1e6c375b886d772f4bd8edddc792d5ea02dd3f01..5ce955fbad8805077527828b3fea610317ba76c7 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/ui/main/home/HomeFragmentViewModel.kt
@@ -2,7 +2,6 @@ package de.rki.coronawarnapp.ui.main.home
 
 import androidx.lifecycle.LiveData
 import androidx.lifecycle.asLiveData
-import androidx.navigation.NavDirections
 import dagger.assisted.AssistedFactory
 import dagger.assisted.AssistedInject
 import de.rki.coronawarnapp.appconfig.AppConfigProvider
@@ -13,6 +12,8 @@ import de.rki.coronawarnapp.coronatest.latestPCRT
 import de.rki.coronawarnapp.coronatest.latestRAT
 import de.rki.coronawarnapp.coronatest.testErrorsSingleEvent
 import de.rki.coronawarnapp.coronatest.type.CoronaTest
+import de.rki.coronawarnapp.coronatest.type.CoronaTest.Type.PCR
+import de.rki.coronawarnapp.coronatest.type.CoronaTest.Type.RAPID_ANTIGEN
 import de.rki.coronawarnapp.coronatest.type.pcr.PCRCoronaTest
 import de.rki.coronawarnapp.coronatest.type.pcr.SubmissionStatePCR
 import de.rki.coronawarnapp.coronatest.type.pcr.toSubmissionState
@@ -48,6 +49,7 @@ import de.rki.coronawarnapp.tracing.states.LowRisk
 import de.rki.coronawarnapp.tracing.states.TracingDisabled
 import de.rki.coronawarnapp.tracing.states.TracingFailed
 import de.rki.coronawarnapp.tracing.states.TracingInProgress
+import de.rki.coronawarnapp.tracing.states.TracingState
 import de.rki.coronawarnapp.tracing.states.TracingStateProvider
 import de.rki.coronawarnapp.tracing.ui.homecards.IncreasedRiskCard
 import de.rki.coronawarnapp.tracing.ui.homecards.LowRiskCard
@@ -86,52 +88,35 @@ import timber.log.Timber
 @Suppress("LongParameterList")
 class HomeFragmentViewModel @AssistedInject constructor(
     dispatcherProvider: DispatcherProvider,
-    private val errorResetTool: EncryptionErrorResetTool,
     tracingStatus: GeneralTracingStatus,
     tracingStateProviderFactory: TracingStateProvider.Factory,
-    private val coronaTestRepository: CoronaTestRepository,
+    coronaTestRepository: CoronaTestRepository,
+    statisticsProvider: StatisticsProvider,
+    vaccinationRepository: VaccinationRepository,
+    private val errorResetTool: EncryptionErrorResetTool,
     private val tracingRepository: TracingRepository,
     private val submissionRepository: SubmissionRepository,
     private val cwaSettings: CWASettings,
     private val appConfigProvider: AppConfigProvider,
-    statisticsProvider: StatisticsProvider,
     private val appShortcutsHelper: AppShortcutsHelper,
     private val tracingSettings: TracingSettings,
     private val traceLocationOrganizerSettings: TraceLocationOrganizerSettings,
     private val timeStamper: TimeStamper,
     private val bluetoothSupport: BluetoothSupport,
     private val vaccinationSettings: VaccinationSettings,
-    private val vaccinationRepository: VaccinationRepository,
 ) : CWAViewModel(dispatcherProvider = dispatcherProvider) {
 
+    private var isLoweredRiskLevelDialogBeingShown = false
     private val tracingStateProvider by lazy { tracingStateProviderFactory.create(isDetailsMode = false) }
+    private val tracingCardItems = tracingStateProvider.state.map { tracingStateItem(it) }.distinctUntilChanged()
 
-    val routeToScreen = SingleLiveEvent<NavDirections>()
-    val openFAQUrlEvent = SingleLiveEvent<Unit>()
-    val openIncompatibleEvent = SingleLiveEvent<Boolean>()
-    val openTraceLocationOrganizerFlow = SingleLiveEvent<Unit>()
-    val openVaccinationRegistrationFlow = SingleLiveEvent<Unit>()
     val errorEvent = SingleLiveEvent<Throwable>()
+    val events = SingleLiveEvent<HomeFragmentEvents>()
 
-    val tracingHeaderState: LiveData<TracingHeaderState> = tracingStatus.generalStatus
-        .map { it.toHeaderState() }
+    val tracingHeaderState: LiveData<TracingHeaderState> = tracingStatus.generalStatus.map { it.toHeaderState() }
         .asLiveData(dispatcherProvider.Default)
-
-    val popupEvents = SingleLiveEvent<HomeFragmentEvents>()
-
     val coronaTestErrors = coronaTestRepository.testErrorsSingleEvent
-        .asLiveData(context = dispatcherProvider.Default)
-
-    fun showPopUps() {
-        launch {
-            if (errorResetTool.isResetNoticeToBeShown) {
-                popupEvents.postValue(ShowErrorResetDialog)
-            }
-            if (!cwaSettings.wasTracingExplanationDialogShown) {
-                popupEvents.postValue(ShowTracingExplanation)
-            }
-        }
-    }
+        .asLiveData(dispatcherProvider.Default)
 
     val showIncorrectDeviceTimeDialog by lazy {
         var wasDeviceTimeDialogShown = false
@@ -148,151 +133,6 @@ class HomeFragmentViewModel @AssistedInject constructor(
         }
     }
 
-    private val tracingCardItems = tracingStateProvider.state.map { tracingState ->
-        when (tracingState) {
-            is TracingInProgress -> TracingProgressCard.Item(
-                state = tracingState,
-                onCardClick = {
-                    routeToScreen.postValue(HomeFragmentDirections.actionMainFragmentToRiskDetailsFragment())
-                }
-            )
-            is TracingDisabled -> TracingDisabledCard.Item(
-                state = tracingState,
-                onCardClick = {
-                    routeToScreen.postValue(HomeFragmentDirections.actionMainFragmentToRiskDetailsFragment())
-                },
-                onEnableTracingClick = {
-                    routeToScreen.postValue(HomeFragmentDirections.actionMainFragmentToSettingsTracingFragment())
-                }
-            )
-            is LowRisk -> LowRiskCard.Item(
-                state = tracingState,
-                onCardClick = {
-                    routeToScreen.postValue(HomeFragmentDirections.actionMainFragmentToRiskDetailsFragment())
-                },
-                onUpdateClick = { refreshRiskResult() }
-            )
-            is IncreasedRisk -> IncreasedRiskCard.Item(
-                state = tracingState,
-                onCardClick = {
-                    routeToScreen.postValue(HomeFragmentDirections.actionMainFragmentToRiskDetailsFragment())
-                },
-                onUpdateClick = { refreshRiskResult() }
-            )
-            is TracingFailed -> TracingFailedCard.Item(
-                state = tracingState,
-                onCardClick = {
-                    routeToScreen.postValue(HomeFragmentDirections.actionMainFragmentToRiskDetailsFragment())
-                },
-                onRetryClick = { refreshRiskResult() }
-            )
-        }
-    }.distinctUntilChanged()
-
-    private fun PCRCoronaTest?.toTestCardItem() = when (val state = this.toSubmissionState()) {
-        is SubmissionStatePCR.NoTest -> TestUnregisteredCard.Item(state) {
-            routeToScreen.postValue(HomeFragmentDirections.actionMainFragmentToSubmissionDispatcher())
-        }
-        is SubmissionStatePCR.FetchingResult -> TestFetchingCard.Item(state)
-        is SubmissionStatePCR.TestResultReady -> PcrTestReadyCard.Item(state) {
-            routeToScreen.postValue(
-                HomeFragmentDirections.actionMainFragmentToSubmissionTestResultAvailableFragment(CoronaTest.Type.PCR)
-            )
-        }
-        is SubmissionStatePCR.TestPositive -> PcrTestPositiveCard.Item(state) {
-            routeToScreen.postValue(
-                HomeFragmentDirections
-                    .actionMainFragmentToSubmissionResultPositiveOtherWarningNoConsentFragment(CoronaTest.Type.PCR)
-            )
-        }
-        is SubmissionStatePCR.TestNegative -> PcrTestNegativeCard.Item(state) {
-            routeToScreen.postValue(
-                HomeFragmentDirections.actionMainFragmentToSubmissionTestResultNegativeFragment(CoronaTest.Type.PCR)
-            )
-        }
-        is SubmissionStatePCR.TestInvalid -> PcrTestInvalidCard.Item(state) {
-            popupEvents.postValue(HomeFragmentEvents.ShowDeleteTestDialog(CoronaTest.Type.PCR))
-        }
-        is SubmissionStatePCR.TestError -> PcrTestErrorCard.Item(state) {
-            routeToScreen.postValue(
-                HomeFragmentDirections
-                    .actionMainFragmentToSubmissionTestResultPendingFragment(testType = CoronaTest.Type.PCR)
-            )
-        }
-        is SubmissionStatePCR.TestPending -> PcrTestPendingCard.Item(state) {
-            routeToScreen.postValue(
-                HomeFragmentDirections
-                    .actionMainFragmentToSubmissionTestResultPendingFragment(
-                        testType = CoronaTest.Type.PCR,
-                        forceTestResultUpdate = true
-                    )
-            )
-        }
-        is SubmissionStatePCR.SubmissionDone -> PcrTestSubmissionDoneCard.Item(state) {
-            routeToScreen.postValue(
-                HomeFragmentDirections
-                    .actionMainFragmentToSubmissionTestResultKeysSharedFragment(CoronaTest.Type.PCR)
-            )
-        }
-    }
-
-    private fun RACoronaTest?.toTestCardItem(coronaTestConfig: CoronaTestConfig) =
-        when (val state = this.toSubmissionState(timeStamper.nowUTC, coronaTestConfig)) {
-            is SubmissionStateRAT.NoTest -> TestUnregisteredCard.Item(state) {
-                routeToScreen.postValue(HomeFragmentDirections.actionMainFragmentToSubmissionDispatcher())
-            }
-            is SubmissionStateRAT.FetchingResult -> TestFetchingCard.Item(state)
-            is SubmissionStateRAT.TestResultReady -> RapidTestReadyCard.Item(state) {
-                routeToScreen.postValue(
-                    HomeFragmentDirections
-                        .actionMainFragmentToSubmissionTestResultAvailableFragment(CoronaTest.Type.RAPID_ANTIGEN)
-                )
-            }
-            is SubmissionStateRAT.TestPositive -> RapidTestPositiveCard.Item(state) {
-                routeToScreen.postValue(
-                    HomeFragmentDirections
-                        .actionMainFragmentToSubmissionResultPositiveOtherWarningNoConsentFragment(
-                            CoronaTest.Type.RAPID_ANTIGEN
-                        )
-                )
-            }
-            is SubmissionStateRAT.TestNegative -> RapidTestNegativeCard.Item(state) {
-                routeToScreen.postValue(
-                    HomeFragmentDirections
-                        .actionMainFragmentToSubmissionNegativeAntigenTestResultFragment()
-                )
-            }
-            is SubmissionStateRAT.TestInvalid -> RapidTestInvalidCard.Item(state) {
-                popupEvents.postValue(HomeFragmentEvents.ShowDeleteTestDialog(CoronaTest.Type.RAPID_ANTIGEN))
-            }
-            is SubmissionStateRAT.TestError -> RapidTestErrorCard.Item(state) {
-                routeToScreen.postValue(
-                    HomeFragmentDirections
-                        .actionMainFragmentToSubmissionTestResultPendingFragment(
-                            testType = CoronaTest.Type.RAPID_ANTIGEN
-                        )
-                )
-            }
-            is SubmissionStateRAT.TestPending -> RapidTestPendingCard.Item(state) {
-                routeToScreen.postValue(
-                    HomeFragmentDirections
-                        .actionMainFragmentToSubmissionTestResultPendingFragment(
-                            testType = CoronaTest.Type.RAPID_ANTIGEN,
-                            forceTestResultUpdate = true
-                        )
-                )
-            }
-            is SubmissionStateRAT.TestOutdated -> RapidTestOutdatedCard.Item(state) {
-                submissionRepository.removeTestFromDevice(type = CoronaTest.Type.RAPID_ANTIGEN)
-            }
-            is SubmissionStateRAT.SubmissionDone -> RapidTestSubmissionDoneCard.Item(state) {
-                routeToScreen.postValue(
-                    HomeFragmentDirections
-                        .actionMainFragmentToSubmissionTestResultKeysSharedFragment(CoronaTest.Type.RAPID_ANTIGEN)
-                )
-            }
-        }
-
     val homeItems: LiveData<List<HomeItem>> = combine(
         tracingCardItems,
         coronaTestRepository.latestPCRT,
@@ -320,7 +160,7 @@ class HomeFragmentViewModel @AssistedInject constructor(
                     VaccinatedPerson.Status.INCOMPLETE -> VaccinationHomeCard.Item(
                         vaccinatedPerson = vaccinatedPerson,
                         onClickAction = {
-                            popupEvents.postValue(
+                            events.postValue(
                                 HomeFragmentEvents.GoToVaccinationList(vaccinatedPerson.identifier.codeSHA256)
                             )
                         }
@@ -328,7 +168,7 @@ class HomeFragmentViewModel @AssistedInject constructor(
                     VaccinatedPerson.Status.IMMUNITY -> ImmuneVaccinationHomeCard.Item(
                         vaccinatedPerson = vaccinatedPerson,
                         onClickAction = {
-                            popupEvents.postValue(
+                            events.postValue(
                                 HomeFragmentEvents.GoToVaccinationList(vaccinatedPerson.identifier.codeSHA256)
                             )
                         }
@@ -338,12 +178,10 @@ class HomeFragmentViewModel @AssistedInject constructor(
             }
 
             if (bluetoothSupport.isAdvertisingSupported == false) {
-
                 val scanningSupported = bluetoothSupport.isScanningSupported != false
-
                 add(
                     IncompatibleCard.Item(
-                        onClickAction = { openIncompatibleEvent.postValue(scanningSupported) },
+                        onClickAction = { events.postValue(HomeFragmentEvents.OpenIncompatibleUrl(scanningSupported)) },
                         bluetoothSupported = scanningSupported
                     )
                 )
@@ -365,9 +203,7 @@ class HomeFragmentViewModel @AssistedInject constructor(
                         add(testRAT.toTestCardItem(coronaTestParameters))
                         add(
                             TestUnregisteredCard.Item(SubmissionStatePCR.NoTest) {
-                                routeToScreen.postValue(
-                                    HomeFragmentDirections.actionMainFragmentToSubmissionDispatcher()
-                                )
+                                events.postValue(HomeFragmentEvents.GoToSubmissionDispatcher)
                             }
                         )
                     } else add(testRAT.toTestCardItem(coronaTestParameters))
@@ -377,7 +213,11 @@ class HomeFragmentViewModel @AssistedInject constructor(
             add(
                 CreateVaccinationHomeCard.Item(
                     onClickAction = {
-                        openVaccinationRegistrationFlow.postValue(Unit)
+                        events.postValue(
+                            HomeFragmentEvents.OpenVaccinationRegistrationGraph(
+                                vaccinationSettings.registrationAcknowledged
+                            )
+                        )
                     }
                 )
             )
@@ -387,22 +227,30 @@ class HomeFragmentViewModel @AssistedInject constructor(
                     StatisticsHomeCard.Item(
                         data = statsData,
                         onHelpAction = {
-                            popupEvents.postValue(HomeFragmentEvents.GoToStatisticsExplanation)
+                            events.postValue(HomeFragmentEvents.GoToStatisticsExplanation)
                         }
                     )
                 )
             }
 
-            add(CreateTraceLocationCard.Item(onClickAction = { openTraceLocationOrganizerFlow.postValue(Unit) }))
+            add(
+                CreateTraceLocationCard.Item(
+                    onClickAction = {
+                        events.postValue(
+                            HomeFragmentEvents.OpenTraceLocationOrganizerGraph(
+                                traceLocationOrganizerSettings.qrInfoAcknowledged
+                            )
+                        )
+                    }
+                )
+            )
 
-            add(FAQCard.Item(onClickAction = { openFAQUrlEvent.postValue(Unit) }))
+            add(FAQCard.Item(onClickAction = { events.postValue(HomeFragmentEvents.OpenFAQUrl) }))
         }
     }
         .distinctUntilChanged()
         .asLiveData(dispatcherProvider.Default)
 
-    private var isLoweredRiskLevelDialogBeingShown = false
-
     // TODO only lazy to keep tests going which would break because of LocalData access
     val showLoweredRiskLevelDialog: LiveData<Boolean> by lazy {
         tracingSettings
@@ -434,16 +282,17 @@ class HomeFragmentViewModel @AssistedInject constructor(
         }
     }
 
+    fun showPopUps() = launch {
+        if (errorResetTool.isResetNoticeToBeShown) events.postValue(ShowErrorResetDialog)
+        if (!cwaSettings.wasTracingExplanationDialogShown) events.postValue(ShowTracingExplanation)
+    }
+
     fun restoreAppShortcuts() {
         launch {
             appShortcutsHelper.restoreAppShortcut()
         }
     }
 
-    private fun refreshRiskResult() {
-        tracingRepository.refreshRiskResult()
-    }
-
     fun deregisterWarningAccepted(type: CoronaTest.Type) {
         submissionRepository.removeTestFromDevice(type)
     }
@@ -461,9 +310,96 @@ class HomeFragmentViewModel @AssistedInject constructor(
         cwaSettings.wasTracingExplanationDialogShown = true
     }
 
-    fun wasQRInfoWasAcknowledged() = traceLocationOrganizerSettings.qrInfoAcknowledged
+    private fun PCRCoronaTest?.toTestCardItem() = when (val state = this.toSubmissionState()) {
+        is SubmissionStatePCR.NoTest -> TestUnregisteredCard.Item(state) {
+            events.postValue(HomeFragmentEvents.GoToSubmissionDispatcher)
+        }
+        is SubmissionStatePCR.FetchingResult -> TestFetchingCard.Item(state)
+        is SubmissionStatePCR.TestResultReady -> PcrTestReadyCard.Item(state) {
+            events.postValue(HomeFragmentEvents.GoToTestResultAvailableFragment(PCR))
+        }
+        is SubmissionStatePCR.TestPositive -> PcrTestPositiveCard.Item(state) {
+            events.postValue(HomeFragmentEvents.GoToTestResultPositiveFragment(PCR))
+        }
+        is SubmissionStatePCR.TestNegative -> PcrTestNegativeCard.Item(state) {
+            events.postValue(HomeFragmentEvents.GoToPcrTestResultNegativeFragment(PCR))
+        }
+        is SubmissionStatePCR.TestInvalid -> PcrTestInvalidCard.Item(state) {
+            events.postValue(HomeFragmentEvents.ShowDeleteTestDialog(PCR))
+        }
+        is SubmissionStatePCR.TestError -> PcrTestErrorCard.Item(state) {
+            events.postValue(HomeFragmentEvents.GoToTestResultPendingFragment(PCR))
+        }
+        is SubmissionStatePCR.TestPending -> PcrTestPendingCard.Item(state) {
+            events.postValue(HomeFragmentEvents.GoToTestResultPendingFragment(PCR, true))
+        }
+        is SubmissionStatePCR.SubmissionDone -> PcrTestSubmissionDoneCard.Item(state) {
+            events.postValue(HomeFragmentEvents.GoToTestResultKeysSharedFragment(PCR))
+        }
+    }
+
+    private fun RACoronaTest?.toTestCardItem(coronaTestConfig: CoronaTestConfig) =
+        when (val state = this.toSubmissionState(timeStamper.nowUTC, coronaTestConfig)) {
+            is SubmissionStateRAT.NoTest -> TestUnregisteredCard.Item(state) {
+                events.postValue(HomeFragmentEvents.GoToSubmissionDispatcher)
+            }
+            is SubmissionStateRAT.FetchingResult -> TestFetchingCard.Item(state)
+            is SubmissionStateRAT.TestResultReady -> RapidTestReadyCard.Item(state) {
+                events.postValue(HomeFragmentEvents.GoToTestResultAvailableFragment(RAPID_ANTIGEN))
+            }
+            is SubmissionStateRAT.TestPositive -> RapidTestPositiveCard.Item(state) {
+                events.postValue(HomeFragmentEvents.GoToTestResultPositiveFragment(RAPID_ANTIGEN))
+            }
+            is SubmissionStateRAT.TestNegative -> RapidTestNegativeCard.Item(state) {
+                events.postValue(HomeFragmentEvents.GoToRapidTestResultNegativeFragment)
+            }
+            is SubmissionStateRAT.TestInvalid -> RapidTestInvalidCard.Item(state) {
+                events.postValue(HomeFragmentEvents.ShowDeleteTestDialog(RAPID_ANTIGEN))
+            }
+            is SubmissionStateRAT.TestError -> RapidTestErrorCard.Item(state) {
+                events.postValue(HomeFragmentEvents.GoToTestResultPendingFragment(RAPID_ANTIGEN))
+            }
+            is SubmissionStateRAT.TestPending -> RapidTestPendingCard.Item(state) {
+                events.postValue(HomeFragmentEvents.GoToTestResultPendingFragment(RAPID_ANTIGEN, true))
+            }
+            is SubmissionStateRAT.TestOutdated -> RapidTestOutdatedCard.Item(state) {
+                submissionRepository.removeTestFromDevice(RAPID_ANTIGEN)
+            }
+            is SubmissionStateRAT.SubmissionDone -> RapidTestSubmissionDoneCard.Item(state) {
+                events.postValue(HomeFragmentEvents.GoToTestResultKeysSharedFragment(RAPID_ANTIGEN))
+            }
+        }
 
-    fun wasVaccinationRegistrationAcknowledged() = vaccinationSettings.registrationAcknowledged
+    private fun refreshRiskResult() {
+        tracingRepository.refreshRiskResult()
+    }
+
+    private fun tracingStateItem(tracingState: TracingState) = when (tracingState) {
+        is TracingInProgress -> TracingProgressCard.Item(
+            state = tracingState,
+            onCardClick = { events.postValue(HomeFragmentEvents.GoToRiskDetailsFragment) }
+        )
+        is TracingDisabled -> TracingDisabledCard.Item(
+            state = tracingState,
+            onCardClick = { events.postValue(HomeFragmentEvents.GoToRiskDetailsFragment) },
+            onEnableTracingClick = { events.postValue(HomeFragmentEvents.GoToSettingsTracingFragment) }
+        )
+        is LowRisk -> LowRiskCard.Item(
+            state = tracingState,
+            onCardClick = { events.postValue(HomeFragmentEvents.GoToRiskDetailsFragment) },
+            onUpdateClick = { refreshRiskResult() }
+        )
+        is IncreasedRisk -> IncreasedRiskCard.Item(
+            state = tracingState,
+            onCardClick = { events.postValue(HomeFragmentEvents.GoToRiskDetailsFragment) },
+            onUpdateClick = { refreshRiskResult() }
+        )
+        is TracingFailed -> TracingFailedCard.Item(
+            state = tracingState,
+            onCardClick = { events.postValue(HomeFragmentEvents.GoToRiskDetailsFragment) },
+            onRetryClick = { refreshRiskResult() }
+        )
+    }
 
     @AssistedFactory
     interface Factory : SimpleCWAViewModelFactory<HomeFragmentViewModel>
diff --git a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ui/FragmentExtensions.kt b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ui/FragmentExtensions.kt
index 4cdc9ec41071c7d3b397661ba3cc01786c07a905..95b2fa47fdf7eca2f5b64ca3a4c471423d22f511 100644
--- a/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ui/FragmentExtensions.kt
+++ b/Corona-Warn-App/src/main/java/de/rki/coronawarnapp/util/ui/FragmentExtensions.kt
@@ -7,10 +7,12 @@ import androidx.fragment.app.FragmentContainerView
 import androidx.fragment.app.FragmentManager
 import androidx.navigation.NavController
 import androidx.navigation.NavDirections
+import androidx.navigation.NavGraph
 import androidx.navigation.fragment.NavHostFragment
 import androidx.navigation.fragment.findNavController
 import de.rki.coronawarnapp.ui.doNavigate
 import timber.log.Timber
+import java.lang.IllegalArgumentException
 
 fun Fragment.doNavigate(direction: NavDirections) = findNavController().doNavigate(direction)
 
@@ -35,3 +37,13 @@ fun FragmentManager.findNavController(@IdRes id: Int): NavController {
     val fragment = findFragmentById(id) ?: throw IllegalStateException("Fragment is not found for id:$id")
     return NavHostFragment.findNavController(fragment)
 }
+
+/**
+ * Finds nested graph [NavGraph] by Id.
+ * @param nestedGraphId
+ * @throws IllegalArgumentException if graph not found
+ */
+fun Fragment.findNestedGraph(@IdRes nestedGraphId: Int): NavGraph {
+    return findNavController().graph.findNode(nestedGraphId) as? NavGraph
+        ?: throw IllegalArgumentException("Nested graph with id=$nestedGraphId not found")
+}
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 95dbddcbfb3017424dbd8d5a3fdd717b1b775b8d..e91b6e0d929306d60e5ecbf988254baa8baeb498 100644
--- a/Corona-Warn-App/src/main/res/navigation/nav_graph.xml
+++ b/Corona-Warn-App/src/main/res/navigation/nav_graph.xml
@@ -312,6 +312,9 @@
         android:name="de.rki.coronawarnapp.ui.submission.testresult.pending.SubmissionTestResultPendingFragment"
         android:label="SubmissionTestResultPendingFragment"
         tools:layout="@layout/fragment_submission_test_result_pending">
+        <argument
+            android:name="testType"
+            app:argType="de.rki.coronawarnapp.coronatest.type.CoronaTest$Type" />
         <argument
             android:name="forceTestResultUpdate"
             android:defaultValue="false"
@@ -334,9 +337,6 @@
             app:destination="@id/submissionTestResultAvailableFragment"
             app:popUpTo="@id/mainFragment"
             app:popUpToInclusive="false" />
-        <argument
-            android:name="testType"
-            app:argType="de.rki.coronawarnapp.coronatest.type.CoronaTest$Type" />
         <action
             android:id="@+id/action_submissionTestResultPendingFragment_to_submissionNegativeAntigenTestResultFragment"
             app:destination="@id/submissionNegativeAntigenTestResultFragment"
diff --git a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt
index a1a3c9983362bf68370a23706727cb4f2c1a96fb..7d9d96f3fa5151fff19408411c86ef342dc572ee 100644
--- a/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt
+++ b/Corona-Warn-App/src/test/java/de/rki/coronawarnapp/main/home/HomeFragmentViewModelTest.kt
@@ -169,7 +169,7 @@ class HomeFragmentViewModelTest : BaseTest() {
 
         with(createInstance()) {
             showPopUps()
-            popupEvents.getOrAwaitValue() shouldBe HomeFragmentEvents.ShowErrorResetDialog
+            events.getOrAwaitValue() shouldBe HomeFragmentEvents.ShowErrorResetDialog
         }
     }
 }