Skip to content

Add Top Categories dashboard card UI#15581

Draft
JorgeMucientes wants to merge 5 commits intoissue/top-categories-data-layerfrom
issue/top-categories-ui
Draft

Add Top Categories dashboard card UI#15581
JorgeMucientes wants to merge 5 commits intoissue/top-categories-data-layerfrom
issue/top-categories-ui

Conversation

@JorgeMucientes
Copy link
Copy Markdown
Contributor

Description

Adds the UI for the Top Categories dashboard widget, building on the data layer from #15580. The card displays product categories ranked by items sold and net sales, with date range selection (Today/Week/Month/Year/Custom) and drill-down into products within a selected category.

UI Components

  • DashboardTopCategoriesViewModel with date range selection and data loading
  • DashboardTopCategoriesWidgetCard Compose UI with table layout showing category name, items sold, and net sales
  • GetSelectedRangeForTopCategories for date range persistence
  • CategoryProductsFragment / CategoryProductsScreen / CategoryProductsViewModel for drill-down into products within a selected category

Widget Registration & Wiring

  • TOP_CATEGORIES added to DashboardWidget.Type enum
  • Routing in DashboardContainer to the card composable
  • DashboardRepository status mapping
  • Navigation graph entries for category products screen
  • String resources for the card UI

Tests

  • Unit tests for DashboardTopCategoriesViewModel

Test Steps

  1. Open the app and navigate to the "My Store" dashboard
  2. Tap the edit (pencil) icon and enable the "Top categories" card
  3. Verify the card shows categories with "Items sold" and "Net sales" columns
  4. Switch between date ranges (Today/Week/Month/Year)
  5. Tap on a category to see products within that category
  6. Verify the "View all store analytics" button works
  7. Verify the card can be hidden via the overflow menu

RELEASE-NOTES.txt

  • I have considered whether this change warrants user-facing release notes and have added them to RELEASE-NOTES.txt if so.

@dangermattic
Copy link
Copy Markdown
Collaborator

dangermattic commented Mar 30, 2026

2 Errors
🚫 Please ensure the PR has the category: tracks label.
🚫 Please add tests for class CategoryProductsViewModel (or add unit-tests-exemption label to ignore this).
1 Warning
⚠️ This PR is larger than 300 lines of changes. Please consider splitting it into smaller PRs for easier and faster reviews.
2 Messages
📖

This PR contains changes to Tracks-related logic. Please ensure (author and reviewer) the following are completed:

  • The tracks events must be validated in the Tracks system.
  • Verify the internal Tracks spreadsheet has also been updated.
  • Please consider registering any new events.
  • The PR must be assigned the category: tracks label.
📖 This PR is still a Draft: some checks will be skipped.

Generated by 🚫 Danger

@wpmobilebot
Copy link
Copy Markdown
Collaborator

wpmobilebot commented Mar 30, 2026

App Icon📲 You can test the changes from this Pull Request in WooCommerce Android by scanning the QR code below to install the corresponding build.

App NameWooCommerce Android
Platform📱 Mobile
FlavorJalapeno
Build TypeDebug
Build Number736
Version24.4-rc-1
Application IDcom.woocommerce.android.prealpha
Commitd90a333
Installation URL4bb3n8j8padig
Automatticians: You can use our internal self-serve MC tool to give yourself access to those builds if needed.

import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material.Divider

Check warning

Code scanning / Android Lint

material and material3 are separate, incompatible design system libraries Warning

Using a material import while also using the material3 library
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material.Divider
import androidx.compose.material.MaterialTheme

Check warning

Code scanning / Android Lint

material and material3 are separate, incompatible design system libraries Warning

Using a material import while also using the material3 library
import androidx.compose.foundation.layout.width
import androidx.compose.material.Divider
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text

Check warning

Code scanning / Android Lint

material and material3 are separate, incompatible design system libraries Warning

Using a material import while also using the material3 library
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material.CircularProgressIndicator

Check warning

Code scanning / Android Lint

material and material3 are separate, incompatible design system libraries Warning

Using a material import while also using the material3 library
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Divider

Check warning

Code scanning / Android Lint

material and material3 are separate, incompatible design system libraries Warning

Using a material import while also using the material3 library
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Divider
import androidx.compose.material.MaterialTheme

Check warning

Code scanning / Android Lint

material and material3 are separate, incompatible design system libraries Warning

Using a material import while also using the material3 library
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Divider
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text

Check warning

Code scanning / Android Lint

material and material3 are separate, incompatible design system libraries Warning

Using a material import while also using the material3 library
@JorgeMucientes JorgeMucientes marked this pull request as draft March 30, 2026 10:03
@JorgeMucientes JorgeMucientes added this to the 24.5 milestone Mar 30, 2026
@JorgeMucientes JorgeMucientes added the feature: analytics In-app store analytics label Mar 30, 2026
@JorgeMucientes JorgeMucientes force-pushed the issue/top-categories-ui branch from 7aa9518 to 8eadf43 Compare March 30, 2026 10:09
Add the ViewModel, Compose UI, and category products screen:
- DashboardTopCategoriesViewModel with date range selection and data loading
- DashboardTopCategoriesWidgetCard with table layout showing category name,
  items sold, and net sales
- GetSelectedRangeForTopCategories for date range persistence
- CategoryProductsFragment/Screen/ViewModel for drill-down into products
  within a selected category
Add TOP_CATEGORIES to DashboardWidget.Type enum, route widget in
DashboardContainer to the card composable, add DashboardRepository
status mapping, navigation graph entries for category products screen,
and string resources for the card UI.
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds the UI layer for a new “Top categories” dashboard widget, including date range selection and a drill-down screen to view products within a selected category.

Changes:

  • Introduces DashboardTopCategoriesViewModel and a new DashboardTopCategoriesWidgetCard Compose card for displaying category leaderboards.
  • Adds navigation + new drill-down destination (CategoryProductsFragment / CategoryProductsScreen / CategoryProductsViewModel) to show products for a selected category and date range.
  • Registers the widget type (TOP_CATEGORIES) and wires it into dashboard rendering, status mapping, resources, and unit tests.

Reviewed changes

Copilot reviewed 12 out of 12 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
WooCommerce/src/test/kotlin/com/woocommerce/android/ui/dashboard/topcategories/DashboardTopCategoriesViewModelTest.kt Adds unit tests for DashboardTopCategoriesViewModel core states/events.
WooCommerce/src/main/res/values/strings.xml Adds strings for the new Top Categories widget and products drill-down title.
WooCommerce/src/main/res/navigation/nav_graph_main.xml Adds nav action from dashboard to category-products destination and defines its arguments.
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topcategories/categoryproducts/CategoryProductsViewModel.kt Adds ViewModel to load products for a category within a time range and emit navigation events.
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topcategories/categoryproducts/CategoryProductsScreen.kt Adds Compose UI to render loading/error/empty/product list states for category products.
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topcategories/categoryproducts/CategoryProductsFragment.kt Adds Fragment hosting the Compose screen and handling product navigation.
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topcategories/GetSelectedRangeForTopCategories.kt Adds date range selection persistence wrapper for the Top Categories card.
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topcategories/DashboardTopCategoriesWidgetCard.kt Adds Compose widget card UI, including range header, list/table layout, and navigation event handling.
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/topcategories/DashboardTopCategoriesViewModel.kt Adds ViewModel for loading categories leaderboard data, date-range behavior, refresh, and analytics/navigation events.
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/data/DashboardRepository.kt Maps TOP_CATEGORIES widget availability status alongside existing widgets.
WooCommerce/src/main/kotlin/com/woocommerce/android/ui/dashboard/DashboardContainer.kt Wires the new widget card into dashboard rendering by widget type.
WooCommerce/src/main/kotlin/com/woocommerce/android/model/DashboardWidget.kt Registers the new TOP_CATEGORIES widget type with title + tracking identifier.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

contentAlignment = Alignment.Center
) {
Text(
text = stringResource(id = R.string.dashboard_top_categories_empty),
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The empty state message uses dashboard_top_categories_empty ("No categories found"), but this screen is showing products within a category. This will display the wrong text when a category has no products; use a products-specific empty string (or reuse an existing "No products" message) instead.

Suggested change
text = stringResource(id = R.string.dashboard_top_categories_empty),
text = stringResource(id = R.string.dashboard_top_performers_empty),

Copilot uses AI. Check for mistakes.
Comment on lines +28 to +29
override fun getFragmentTitle() =
viewModel.state.value?.categoryName ?: ""
Copy link

Copilot AI Mar 30, 2026

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

getFragmentTitle() currently reads from viewModel.state.value?.categoryName, but state is derived via StateFlow.asLiveData() and may be null until the LiveData becomes active, resulting in a blank toolbar title. Also, the new dashboard_top_categories_products_title ("Products in %s") string isn’t used, which differs from the PR description. Prefer deriving the title directly from nav args (or a non-LiveData property) and format it with the localized string resource.

Copilot uses AI. Check for mistakes.
Display only the formatted currency amount in the top categories
card rows instead of prefixing it with "Net sales:".
Use fixed column widths for Items sold and Net sales columns
so numbers align vertically across all category rows.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

feature: analytics In-app store analytics

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants