Repository: wordpress-mobile/WordPress-Android (language: kotlin)

Issue:
Dashboard Cards Personalization shows in eligible cards 
### Expected behavior
For a site or user not having the capability of a feature, the card personalization for that card should not be shown 

### Actual behavior
The ability to hide/show a card of a feature that isn't available for the user is shown in the dashboard personalization screen

For example, the below screen shows blaze card hide/show ability but the feature is not available on the site

<img src="https://github.com/wordpress-mobile/WordPress-Android/assets/17463767/1e840fe8-77cc-48ee-9318-3d8cfc5ddba3" width="250" height="530">

### Steps to reproduce the behavior
- Go to Jetpack app and login to an account without having Blaze, Activity log or Post edit capability
- Go to Dashboard 
- Click on Personalize your Home tab 
- Notice that Blaze or Activity Log card hide/show toggle is shown

##### Tested on [device], Android [version], JPAndroid / WPAndroid [version]
Pixel 4a, Android 13



Discussion hints:

Pull request: Fixes: In eligible cards shown in Personalization Screen 
## Fixes 
#19467

## Description
This PR fixes the scenario in which the in eligible feature cards were shown in the personalization screen This PR adds a check before adding the visibility options for a feature card in personalization screen. 

Note: the shortcuts personalization already was checking whether a feature is available for a site before showing it on the screen

| Before  |  After | 
|---|---|
| <img src="https://github.com/wordpress-mobile/WordPress-Android/assets/17463767/1e840fe8-77cc-48ee-9318-3d8cfc5ddba3" width="250" height="530"> | <img width="250" height="530" alt="Screenshot 2023-10-28 at 6 51 58 PM" src="https://github.com/wordpress-mobile/WordPress-Android/assets/17463767/3119678b-b736-47de-aec2-e18396cf4336"> |   

## To test:
### Blaze feature is shown/hidden 
1. Login to the jetpack app with a site which doesn't have blaze capability - 
2. Go to Dashboard
3. Click on Personalize your Home Card 
4. Go to Dashboard Cards
5. Verify that blaze card visibility toggle is not shown 
6. Login to the Jetpack app with site having blaze capability
7. Follow steps 2-4
8. Verify that blaze card visibility toggle is shown

### Activity log card toggle is shown/hidden 
1. Login to the jetpack app with a site which doesn't have Activity log capability
2. Go to Dashboard
3. Click on Personalize your Home Card 
4. Go to Dashboard Cards
5. Verify that Activity log visibility toggle is not shown 
6. Login to the Jetpack app with site having activity log card capability - (manage content/admin)
7. Follow steps 2-4
8. Verify that Activity log visibility toggle is shown

### Pages Card toggle is shown/hidden

### Pages card role logic

| Role  | Can see pages card | 
|---|---|
| Subscriber | N  | 
| Contributor   | N  | 
| Author | N  | 
| Editor  | Y  | 
| Administrator | Y  | 
| Super Admin  |  Y | 

1. Login to the jetpack app with a site which doesn't have Pages capability
2. Go to Dashboard
3. Click on Personalize your Home Card 
4. Go to Dashboard Cards
5. Verify that Pages card visibility toggle is not shown 
6. Login to the Jetpack app with site having Pages capability - see the table above
7. Follow steps 2-4
8. Verify that Pages card visibility toggle is shown

## Regression Notes
1. Potential unintended areas of impact

2. What I did to test those areas of impact (or what existing automated tests I relied on)

3. What automated tests I added (or what prevented me from doing so)

PR submission checklist:
- [x] I have completed the Regression Notes.
- [x] I have considered adding accessibility improvements for my changes.
- [x] I have considered if this change warrants user-facing release notes and have added them to `RELEASE-NOTES.txt` if necessary.

UI Changes testing checklist:
- [x] Portrait and landscape orientations.
- [x] Light and dark modes.
- [x] Fonts: Larger, smaller and bold text.
- [x] High contrast.
- [x] Talkback.
- [x] Languages with large words or with letters/accents not frequently used in English.
- [x] Right-to-left languages. (Even if translation isn’t complete, formatting should still respect the right-to-left layout)
- [x] Large and small screen sizes. (Tablet and smaller phones)
- [x] Multi-tasking: Split screen and Pop-up view. (Android 10 or higher)


Test command: ./gradlew :WordPress:testWordpressVanillaDebugUnitTest --tests "org.wordpress.android.ui.mysite.personalization.DashboardCardPersonalizationViewModelSliceTest"

Fix patch:
diff --git a/WordPress/src/main/java/org/wordpress/android/ui/mysite/personalization/DashboardCardPersonalizationViewModelSlice.kt b/WordPress/src/main/java/org/wordpress/android/ui/mysite/personalization/DashboardCardPersonalizationViewModelSlice.kt
index 62149c0368bd..8d25b5d32a73 100644
--- a/WordPress/src/main/java/org/wordpress/android/ui/mysite/personalization/DashboardCardPersonalizationViewModelSlice.kt
+++ b/WordPress/src/main/java/org/wordpress/android/ui/mysite/personalization/DashboardCardPersonalizationViewModelSlice.kt
@@ -9,8 +9,11 @@ import kotlinx.coroutines.flow.firstOrNull
 import kotlinx.coroutines.launch
 import org.wordpress.android.R
 import org.wordpress.android.analytics.AnalyticsTracker
+import org.wordpress.android.fluxc.model.SiteModel
 import org.wordpress.android.fluxc.store.BloggingRemindersStore
 import org.wordpress.android.modules.BG_THREAD
+import org.wordpress.android.ui.blaze.BlazeFeatureUtils
+import org.wordpress.android.ui.bloggingprompts.BloggingPromptsSettingsHelper
 import org.wordpress.android.ui.mysite.SelectedSiteRepository
 import org.wordpress.android.ui.mysite.cards.dashboard.posts.PostCardType
 import org.wordpress.android.ui.prefs.AppPrefsWrapper
@@ -24,6 +27,8 @@ class DashboardCardPersonalizationViewModelSlice @Inject constructor(
     private val selectedSiteRepository: SelectedSiteRepository,
     private val bloggingRemindersStore: BloggingRemindersStore,
     private val analyticsTrackerWrapper: AnalyticsTrackerWrapper,
+    private val blazeFeatureUtils: BlazeFeatureUtils,
+    private val bloggingPromptsSettingsHelper: BloggingPromptsSettingsHelper
 ) {
     private val _uiState = MutableLiveData<List<DashboardCardState>>()
     val uiState: LiveData<List<DashboardCardState>> = _uiState
@@ -41,52 +46,90 @@ class DashboardCardPersonalizationViewModelSlice @Inject constructor(
     }
 
     private suspend fun getCardStates(siteId: Long): List<DashboardCardState> {
-        return listOf(
-            DashboardCardState(
-                title = R.string.personalization_screen_stats_card_title,
-                description = R.string.personalization_screen_stats_card_description,
-                enabled = isStatsCardShown(siteId),
-                cardType = CardType.STATS
-            ),
-            DashboardCardState(
-                title = R.string.personalization_screen_draft_posts_card_title,
-                description = R.string.personalization_screen_draft_posts_card_description,
-                enabled = isDraftPostsCardShown(siteId),
-                cardType = CardType.DRAFT_POSTS
-            ),
-            DashboardCardState(
-                title = R.string.personalization_screen_scheduled_posts_card_title,
-                description = R.string.personalization_screen_scheduled_posts_card_description,
-                enabled = isScheduledPostsCardShown(siteId),
-                cardType = CardType.SCHEDULED_POSTS
-            ),
-            DashboardCardState(
-                title = R.string.personalization_screen_pages_card_title,
-                description = R.string.personalization_screen_pages_card_description,
-                enabled = isPagesCardShown(siteId),
-                cardType = CardType.PAGES
-            ),
-            DashboardCardState(
-                title = R.string.personalization_screen_activity_log_card_title,
-                description = R.string.personalization_screen_activity_log_card_description,
-                enabled = isActivityLogCardShown(siteId),
-                cardType = CardType.ACTIVITY_LOG
-            ),
+        val selectedSite = selectedSiteRepository.getSelectedSite()
+        val dashboardCardStates = mutableListOf<DashboardCardState>()
+        dashboardCardStates.add(statsCard(siteId))
+        dashboardCardStates.add(draftPostsCard(siteId))
+        dashboardCardStates.add(getScheduledPostsCard(siteId))
+        selectedSite?.let {
+            getPagesCardState(siteId, selectedSite)?.let { dashboardCardStates.add(it) }
+            getActivityLogCard(siteId, selectedSite)?.let { dashboardCardStates.add(it) }
+            getBlazeCardState(siteId, selectedSite)?.let { dashboardCardStates.add(it) }
+        }
+        getBloggingPromptCardState()?.let { dashboardCardStates.add(it) }
+        return dashboardCardStates.toList()
+    }
+
+    private suspend fun getBloggingPromptCardState(): DashboardCardState? {
+        return if (bloggingPromptsSettingsHelper.shouldShowPromptsFeature()) {
             DashboardCardState(
+                title = R.string.personalization_screen_blogging_prompts_card_title,
+                description = R.string.personalization_screen_blogging_prompts_card_description,
+                enabled = isPromptsSettingEnabled(selectedSiteRepository.getSelectedSiteLocalId()),
+                cardType = CardType.BLOGGING_PROMPTS
+            )
+        } else null
+    }
+
+    private fun getBlazeCardState(siteId: Long, selectedSite: SiteModel): DashboardCardState? {
+        if (blazeFeatureUtils.isSiteBlazeEligible(selectedSite)) {
+            return DashboardCardState(
                 title = R.string.personalization_screen_blaze_card_title,
                 description = R.string.personalization_screen_blaze_card_description,
                 enabled = isBlazeCardShown(siteId),
                 cardType = CardType.BLAZE
-            ),
+            )
+        }
+        return null
+    }
+
+    private fun getActivityLogCard(siteId: Long, selectedSite: SiteModel): DashboardCardState? {
+        if (selectedSite.hasCapabilityManageOptions && !selectedSite.isWpForTeamsSite) {
+            return DashboardCardState(
+                title = R.string.personalization_screen_activity_log_card_title,
+                description = R.string.personalization_screen_activity_log_card_description,
+                enabled = isActivityLogCardShown(siteId),
+                cardType = CardType.ACTIVITY_LOG
+            )
+        }
+        return null
+    }
+
+    private fun getScheduledPostsCard(siteId: Long) = DashboardCardState(
+        title = R.string.personalization_screen_scheduled_posts_card_title,
+        description = R.string.personalization_screen_scheduled_posts_card_description,
+        enabled = isScheduledPostsCardShown(siteId),
+        cardType = CardType.SCHEDULED_POSTS
+    )
+
+    private fun draftPostsCard(siteId: Long) = DashboardCardState(
+        title = R.string.personalization_screen_draft_posts_card_title,
+        description = R.string.personalization_screen_draft_posts_card_description,
+        enabled = isDraftPostsCardShown(siteId),
+        cardType = CardType.DRAFT_POSTS
+    )
+
+    private fun statsCard(siteId: Long) = DashboardCardState(
+        title = R.string.personalization_screen_stats_card_title,
+        description = R.string.personalization_screen_stats_card_description,
+        enabled = isStatsCardShown(siteId),
+        cardType = CardType.STATS
+    )
+
+    private fun getPagesCardState(siteId: Long, selectedSite: SiteModel): DashboardCardState? {
+        return if (selectedSite.hasCapabilityEditPages || selectedSite.isSelfHostedAdmin) {
             DashboardCardState(
-                title = R.string.personalization_screen_blogging_prompts_card_title,
-                description = R.string.personalization_screen_blogging_prompts_card_description,
-                enabled = isPromptsSettingEnabled(selectedSiteRepository.getSelectedSiteLocalId()),
-                cardType = CardType.BLOGGING_PROMPTS
+                title = R.string.personalization_screen_pages_card_title,
+                description = R.string.personalization_screen_pages_card_description,
+                enabled = isPagesCardShown(siteId),
+                cardType = CardType.PAGES
             )
-        )
+        } else {
+            null
+        }
     }
 
+
     fun onCardToggled(cardType: CardType, enabled: Boolean) {
         val siteId = selectedSiteRepository.getSelectedSite()!!.siteId
         scope.launch(bgDispatcher) {
@@ -154,6 +197,7 @@ class DashboardCardPersonalizationViewModelSlice @Inject constructor(
     private fun isActivityLogCardShown(siteId: Long) = !appPrefsWrapper.getShouldHideActivityDashboardCard(siteId)
 
     private fun isBlazeCardShown(siteId: Long) = !appPrefsWrapper.hideBlazeCard(siteId)
+
     private suspend fun isPromptsSettingEnabled(
         siteId: Int
     ): Boolean = bloggingRemindersStore


Test patch:
diff --git a/WordPress/src/test/java/org/wordpress/android/ui/mysite/personalization/DashboardCardPersonalizationViewModelSliceTest.kt b/WordPress/src/test/java/org/wordpress/android/ui/mysite/personalization/DashboardCardPersonalizationViewModelSliceTest.kt
index c6074d3d76fa..6e2530ccf16c 100644
--- a/WordPress/src/test/java/org/wordpress/android/ui/mysite/personalization/DashboardCardPersonalizationViewModelSliceTest.kt
+++ b/WordPress/src/test/java/org/wordpress/android/ui/mysite/personalization/DashboardCardPersonalizationViewModelSliceTest.kt
@@ -16,6 +16,8 @@ import org.wordpress.android.analytics.AnalyticsTracker
 import org.wordpress.android.fluxc.model.BloggingRemindersModel
 import org.wordpress.android.fluxc.model.SiteModel
 import org.wordpress.android.fluxc.store.BloggingRemindersStore
+import org.wordpress.android.ui.blaze.BlazeFeatureUtils
+import org.wordpress.android.ui.bloggingprompts.BloggingPromptsSettingsHelper
 import org.wordpress.android.ui.mysite.SelectedSiteRepository
 import org.wordpress.android.ui.mysite.cards.dashboard.posts.PostCardType
 import org.wordpress.android.ui.prefs.AppPrefsWrapper
@@ -36,6 +38,12 @@ class DashboardCardPersonalizationViewModelSliceTest : BaseUnitTest() {
     @Mock
     lateinit var analyticsTrackerWrapper: AnalyticsTrackerWrapper
 
+    @Mock
+    lateinit var blazeFeatureUtils: BlazeFeatureUtils
+
+    @Mock
+    lateinit var bloggingPromptsSettingsHelper: BloggingPromptsSettingsHelper
+
     private lateinit var viewModelSlice: DashboardCardPersonalizationViewModelSlice
 
     private val site = SiteModel().apply { siteId = 123L }
@@ -54,12 +62,19 @@ class DashboardCardPersonalizationViewModelSliceTest : BaseUnitTest() {
         whenever(bloggingRemindersStore.bloggingRemindersModel(localSiteId))
             .thenReturn(flowOf(userSetBloggingRemindersModel))
 
+        whenever(blazeFeatureUtils.isSiteBlazeEligible(site)).thenReturn(true)
+        test {
+            whenever(bloggingPromptsSettingsHelper.shouldShowPromptsFeature()).thenReturn(true)
+        }
+
         viewModelSlice = DashboardCardPersonalizationViewModelSlice(
             bgDispatcher = testDispatcher(),
             appPrefsWrapper = appPrefsWrapper,
             selectedSiteRepository = selectedSiteRepository,
             bloggingRemindersStore = bloggingRemindersStore,
-            analyticsTrackerWrapper = analyticsTrackerWrapper
+            analyticsTrackerWrapper = analyticsTrackerWrapper,
+            blazeFeatureUtils = blazeFeatureUtils,
+            bloggingPromptsSettingsHelper = bloggingPromptsSettingsHelper
         )
 
         viewModelSlice.uiState.observeForever {
@@ -103,6 +118,8 @@ class DashboardCardPersonalizationViewModelSliceTest : BaseUnitTest() {
     @Test
     fun `given pages card is not hidden, when cards are fetched, then state is checked`() {
         whenever(appPrefsWrapper.getShouldHidePagesDashboardCard(123L)).thenReturn(false)
+        site.hasCapabilityEditPages = true
+        site.setIsSelfHostedAdmin(true)
 
         viewModelSlice.start(123L)
         val statsCardState = uiStateList.last().find { it.cardType == CardType.PAGES }
@@ -113,6 +130,8 @@ class DashboardCardPersonalizationViewModelSliceTest : BaseUnitTest() {
     @Test
     fun `given activity log card is not hidden, when cards are fetched, then state is checked`() {
         whenever(appPrefsWrapper.getShouldHideActivityDashboardCard(123L)).thenReturn(false)
+        site.hasCapabilityManageOptions = true
+        site.setIsWpForTeamsSite(false)
 
         viewModelSlice.start(123L)
         val statsCardState = uiStateList.last().find { it.cardType == CardType.ACTIVITY_LOG }
@@ -124,6 +143,7 @@ class DashboardCardPersonalizationViewModelSliceTest : BaseUnitTest() {
     fun `given blaze card is not hidden, when cards are fetched, then state is checked`() {
         whenever(appPrefsWrapper.hideBlazeCard(123L)).thenReturn(false)
 
+
         viewModelSlice.start(123L)
         val statsCardState = uiStateList.last().find { it.cardType == CardType.BLAZE }