Skip to content

Conversation

@Aqil-Ahmad
Copy link
Contributor

@Aqil-Ahmad Aqil-Ahmad commented Nov 25, 2025

What does this PR do?

/fixes #332
/claim #332

Key Changes

  • implements product listing with grid/table views
  • adds filtering by type/category and pagination
  • dual view modes (grid/table) with responsive layout
  • integration with Products and CMS services

Media (Loom or gif)
image
image

Summary by CodeRabbit

  • New Features

    • Product List block: filters, sorting, grid/table views, pagination, product details links, localized labels and no-results.
    • Multi-language product listing pages (EN/DE/PL).
    • Client & server renderers with loading states and SDK endpoint to fetch product lists.
    • Storybook story showcasing a fully populated Product List for previewing UI and interactions.
  • Chores

    • Cross-platform frontend build script updated for file copying.

✏️ Tip: You can customize this high-level summary in your review settings.

@opirebot
Copy link

opirebot bot commented Nov 25, 2025

👀 We've notified the reward creators here.
Make sure your payment account is ready to receive the payment for your hard work 💪

@coderabbitai
Copy link

coderabbitai bot commented Nov 25, 2025

Pre-merge checks and finishing touches

❌ Failed checks (1 warning)
Check name Status Explanation Resolution
Description check ⚠️ Warning The PR description includes key sections (What does this PR do, Key Changes, Media) but omits the 'Related Ticket(s)' section header and lacks testing instructions required by the template. Add a 'Related Ticket(s)' section and comprehensive 'How to test' steps with detailed setup and validation instructions.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: implementing a product list block with grid and table view capabilities.
Linked Issues check ✅ Passed The PR implements all primary coding requirements: product-list block scaffolding, Products/CMS service integration, API harmonization, frontend grid/table views, filters, pagination, localized mocked pages, and renderBlocks.tsx registration.
Out of Scope Changes check ✅ Passed All changes are scoped to product-list block implementation. Frontend package.json updates (shx dependency) support cross-platform build operations, which is a necessary supporting change for the block's build tooling.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (8)
packages/blocks/product-list/lint-staged.config.mjs (1)

1-4: lint‑staged setup is sound; consider typecheck cost on large changes

Running Prettier on staged JS/TS/CSS/SCSS plus a full tsc --noEmit on any TS change is a solid safety net. On larger workspaces this can slow down commits a bit; if it ever becomes painful you could narrow the TypeScript check (e.g., dedicated tsconfig or a lighter command) while keeping this structure. For now, this is perfectly fine to ship.

packages/blocks/product-list/package.json (1)

1-55: Block manifest wiring looks correct; lint glob is slightly broader than necessary

The exports map, build/dev scripts, and dependency sets all look consistent with other block packages and with the dist/api-harmonization layout you’ve configured, including the dedicated ./client entry. The lint script’s pattern "{src,apps,libs,test}/**/*.ts" is a bit broader than this package needs (only src exists here), but it’s harmless—ESLint will just receive a couple of unmatched globs. If you ever want to tighten it, you can safely scope it to src/**/*.ts for slightly faster linting.

packages/blocks/product-list/src/frontend/ProductList.server.tsx (1)

12-26: Consider logging errors before returning null.

The server component correctly fetches data and passes it to the client component. However, the error handling silently returns null without logging. Consider adding error logging for debugging and monitoring purposes.

Apply this diff to add error logging:

     } catch (_error) {
+        console.error('Failed to fetch product list:', _error);
         return null;
     }
packages/blocks/product-list/src/api-harmonization/product-list.mapper.ts (1)

5-25: Mapping logic is sound; consider reducing as unknown as casting

The overall mapProductList wiring (CMS block metadata + products list) looks correct and matches the ProductListBlock model. The double cast on filters and table is a reasonable escape hatch, but if/when CMS and harmonized models diverge it may hide structural mismatches. When you have time, consider tightening these types so the casts are either not needed or reduced to a single, well-documented conversion point.

packages/blocks/product-list/src/api-harmonization/product-list.controller.ts (1)

12-21: Controller wiring is fine; consider adding an explicit return type

The controller correctly delegates to ProductListService.getProductListBlock with typed headers and query. For clarity and future refactors, you may want to add an explicit return type (e.g. Observable<ProductListBlock>) to getProductListBlock, mirroring the service signature.

packages/blocks/product-list/src/api-harmonization/product-list.service.ts (1)

18-37: Service flow is correct; tighten limit/offset handling and Rx chain

The overall flow (CMS block → derive params → Products list → mapProductList) looks good. Two small improvements to consider:

  • Replace || with nullish coalescing so explicit 0 values can be honored and intent is clearer:
- limit: query.limit || cms.pagination?.limit || 12,
- offset: query.offset || 0,
+ limit: query.limit ?? cms.pagination?.limit ?? 12,
+ offset: query.offset ?? 0,
  • Since there is only one upstream observable, forkJoin([cms]) could be simplified to cms.pipe(concatMap(...)) for readability.
packages/blocks/product-list/src/api-harmonization/index.ts (1)

1-8: Centralize the URL constant to avoid duplication

This index defines export const URL = '/blocks/product-list';, and the client file (product-list.client.ts) also exports the same literal. To avoid accidental divergence later, consider having one canonical definition (e.g., keep it here and import/re-export it from the client) so both server and client always agree on the route.

packages/framework/src/modules/cms/models/blocks/product-list.model.ts (1)

5-5: ProductKeys union collapses to string, defeating type safety.

The union keyof Product | string | '__typename' effectively resolves to just string because string is a supertype that includes all string literals. This means the type narrowing attempted in the subsequent type aliases (lines 7-27) doesn't actually provide any compile-time type safety for the id fields.

Consider one of these approaches:

Option 1 (if type safety is desired): Remove | string to restrict IDs to actual Product keys:

-type ProductKeys = keyof Product | string | '__typename';
+type ProductKeys = keyof Product | '__typename';

Option 2 (if flexibility is needed): If any string is intentionally allowed (e.g., for nested properties or computed fields), simplify to just string:

-type ProductKeys = keyof Product | string | '__typename';
+type ProductKeys = string;
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 0d1b8cc and 67e91cd.

⛔ Files ignored due to path filters (1)
  • package-lock.json is excluded by !**/package-lock.json
📒 Files selected for processing (34)
  • apps/api-harmonization/src/app.module.ts (2 hunks)
  • apps/api-harmonization/src/modules/page/page.model.ts (2 hunks)
  • apps/frontend/package.json (2 hunks)
  • apps/frontend/src/blocks/renderBlocks.tsx (2 hunks)
  • packages/blocks/product-list/.gitignore (1 hunks)
  • packages/blocks/product-list/.prettierrc.mjs (1 hunks)
  • packages/blocks/product-list/eslint.config.mjs (1 hunks)
  • packages/blocks/product-list/lint-staged.config.mjs (1 hunks)
  • packages/blocks/product-list/package.json (1 hunks)
  • packages/blocks/product-list/src/api-harmonization/index.ts (1 hunks)
  • packages/blocks/product-list/src/api-harmonization/product-list.client.ts (1 hunks)
  • packages/blocks/product-list/src/api-harmonization/product-list.controller.ts (1 hunks)
  • packages/blocks/product-list/src/api-harmonization/product-list.mapper.ts (1 hunks)
  • packages/blocks/product-list/src/api-harmonization/product-list.model.ts (1 hunks)
  • packages/blocks/product-list/src/api-harmonization/product-list.module.ts (1 hunks)
  • packages/blocks/product-list/src/api-harmonization/product-list.request.ts (1 hunks)
  • packages/blocks/product-list/src/api-harmonization/product-list.service.ts (1 hunks)
  • packages/blocks/product-list/src/frontend/ProductList.client.tsx (1 hunks)
  • packages/blocks/product-list/src/frontend/ProductList.renderer.tsx (1 hunks)
  • packages/blocks/product-list/src/frontend/ProductList.server.tsx (1 hunks)
  • packages/blocks/product-list/src/frontend/ProductList.types.ts (1 hunks)
  • packages/blocks/product-list/src/frontend/index.ts (1 hunks)
  • packages/blocks/product-list/src/sdk/index.ts (1 hunks)
  • packages/blocks/product-list/src/sdk/product-list.ts (1 hunks)
  • packages/blocks/product-list/tsconfig.api.json (1 hunks)
  • packages/blocks/product-list/tsconfig.frontend.json (1 hunks)
  • packages/blocks/product-list/tsconfig.json (1 hunks)
  • packages/blocks/product-list/tsconfig.sdk.json (1 hunks)
  • packages/framework/src/modules/cms/cms.model.ts (1 hunks)
  • packages/framework/src/modules/cms/models/blocks/product-list.model.ts (1 hunks)
  • packages/integrations/mocked/src/modules/cms/cms.service.ts (2 hunks)
  • packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.product-list.mapper.ts (1 hunks)
  • packages/integrations/mocked/src/modules/cms/mappers/cms.page.mapper.ts (8 hunks)
  • packages/integrations/mocked/src/modules/cms/mappers/mocks/pages/product-list.page.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (2)
📚 Learning: 2025-11-14T14:34:25.489Z
Learnt from: marcinkrasowski
Repo: o2sdev/openselfservice PR: 357
File: packages/blocks/ticket-summary/eslint.config.mjs:1-18
Timestamp: 2025-11-14T14:34:25.489Z
Learning: ESLint v9+ provides `defineConfig` as an export from 'eslint/config' module, which supports an `extends` array property in flat config objects for composing configurations.

Applied to files:

  • packages/blocks/product-list/.prettierrc.mjs
  • packages/blocks/product-list/eslint.config.mjs
📚 Learning: 2025-11-14T14:24:34.907Z
Learnt from: marcinkrasowski
Repo: o2sdev/openselfservice PR: 357
File: packages/blocks/ticket-summary/src/frontend/TicketSummary.types.ts:14-16
Timestamp: 2025-11-14T14:24:34.907Z
Learning: In the openselfservice repository, the pattern `Omit<PropsType, ''>` in TypeScript type definitions is intentionally used as a template for future prop omissions, even though it currently does nothing. This convention is preferred for consistency across blocks, making it easier to add omissions when needed later.

Applied to files:

  • packages/blocks/product-list/src/frontend/ProductList.types.ts
🧬 Code graph analysis (15)
packages/framework/src/modules/cms/cms.model.ts (2)
packages/blocks/product-list/src/api-harmonization/product-list.model.ts (1)
  • ProductListBlock (7-28)
packages/framework/src/modules/cms/models/blocks/product-list.model.ts (1)
  • ProductListBlock (29-46)
packages/blocks/product-list/src/frontend/ProductList.renderer.tsx (5)
packages/blocks/product-list/src/frontend/index.ts (2)
  • ProductListRenderer (3-3)
  • ProductList (2-2)
packages/blocks/product-list/src/frontend/ProductList.types.ts (1)
  • ProductListRendererProps (14-16)
packages/ui/src/components/Container/Container.tsx (1)
  • Container (42-62)
packages/blocks/product-list/src/api-harmonization/product-list.model.ts (1)
  • ProductList (30-33)
packages/blocks/product-list/src/frontend/ProductList.server.tsx (1)
  • ProductList (12-26)
packages/blocks/product-list/src/sdk/index.ts (2)
packages/framework/src/sdk.ts (1)
  • extendSdk (140-148)
packages/blocks/product-list/src/sdk/product-list.ts (1)
  • productList (10-32)
apps/frontend/src/blocks/renderBlocks.tsx (3)
packages/blocks/product-list/src/api-harmonization/product-list.model.ts (1)
  • ProductList (30-33)
packages/blocks/product-list/src/frontend/ProductList.server.tsx (1)
  • ProductList (12-26)
packages/blocks/product-list/src/frontend/index.ts (1)
  • ProductList (2-2)
packages/integrations/mocked/src/modules/cms/cms.service.ts (3)
packages/framework/src/modules/cms/cms.request.ts (1)
  • GetCmsEntryParams (1-4)
packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.product-list.mapper.ts (1)
  • mapProductListBlock (276-287)
packages/integrations/mocked/src/utils/delay.ts (1)
  • responseDelay (4-7)
packages/blocks/product-list/src/sdk/product-list.ts (7)
packages/blocks/product-list/src/api-harmonization/index.ts (1)
  • URL (1-1)
packages/blocks/product-list/src/api-harmonization/product-list.client.ts (1)
  • URL (1-1)
packages/blocks/product-list/src/sdk/index.ts (1)
  • sdk (24-28)
packages/blocks/product-list/src/api-harmonization/product-list.request.ts (1)
  • GetProductListBlockQuery (3-10)
packages/framework/src/utils/models/headers.ts (1)
  • AppHeaders (1-6)
packages/blocks/product-list/src/api-harmonization/product-list.model.ts (1)
  • ProductListBlock (7-28)
packages/framework/src/modules/cms/models/blocks/product-list.model.ts (1)
  • ProductListBlock (29-46)
apps/api-harmonization/src/modules/page/page.model.ts (3)
packages/blocks/product-list/src/api-harmonization/product-list.model.ts (2)
  • ProductList (30-33)
  • ProductListBlock (7-28)
packages/blocks/product-list/src/frontend/ProductList.server.tsx (1)
  • ProductList (12-26)
packages/blocks/product-list/src/frontend/index.ts (1)
  • ProductList (2-2)
packages/blocks/product-list/src/api-harmonization/index.ts (1)
packages/blocks/product-list/src/api-harmonization/product-list.client.ts (1)
  • URL (1-1)
packages/blocks/product-list/src/frontend/ProductList.server.tsx (4)
packages/blocks/product-list/src/api-harmonization/product-list.model.ts (1)
  • ProductList (30-33)
packages/blocks/product-list/src/frontend/index.ts (1)
  • ProductList (2-2)
packages/blocks/product-list/src/frontend/ProductList.types.ts (1)
  • ProductListProps (5-10)
packages/blocks/product-list/src/sdk/index.ts (1)
  • sdk (24-28)
packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.product-list.mapper.ts (2)
packages/blocks/product-list/src/api-harmonization/product-list.model.ts (1)
  • ProductListBlock (7-28)
packages/framework/src/modules/cms/models/blocks/product-list.model.ts (1)
  • ProductListBlock (29-46)
packages/blocks/product-list/src/frontend/ProductList.types.ts (3)
packages/blocks/product-list/src/api-harmonization/product-list.model.ts (1)
  • ProductListBlock (7-28)
packages/framework/src/modules/cms/models/blocks/product-list.model.ts (1)
  • ProductListBlock (29-46)
packages/integrations/strapi-cms/generated/strapi.ts (1)
  • Omit (14-14)
apps/api-harmonization/src/app.module.ts (4)
packages/blocks/product-list/src/api-harmonization/product-list.model.ts (1)
  • ProductList (30-33)
packages/blocks/product-list/src/frontend/ProductList.server.tsx (1)
  • ProductList (12-26)
packages/blocks/product-list/src/frontend/index.ts (1)
  • ProductList (2-2)
apps/api-harmonization/src/app.config.ts (1)
  • AppConfig (20-37)
packages/blocks/product-list/src/api-harmonization/product-list.model.ts (5)
packages/framework/src/modules/cms/models/blocks/product-list.model.ts (1)
  • ProductListBlock (29-46)
packages/framework/src/utils/models/filters.ts (1)
  • Filters (1-10)
packages/blocks/product-list/src/frontend/ProductList.server.tsx (1)
  • ProductList (12-26)
packages/framework/src/utils/models/price.ts (1)
  • Price (3-7)
packages/framework/src/utils/models/media.ts (1)
  • Media (1-7)
packages/blocks/product-list/src/api-harmonization/product-list.service.ts (5)
packages/integrations/mocked/src/modules/cms/cms.service.ts (1)
  • Injectable (42-195)
packages/blocks/product-list/src/api-harmonization/product-list.request.ts (1)
  • GetProductListBlockQuery (3-10)
packages/framework/src/utils/models/headers.ts (1)
  • AppHeaders (1-6)
packages/blocks/product-list/src/api-harmonization/product-list.model.ts (1)
  • ProductListBlock (7-28)
packages/blocks/product-list/src/api-harmonization/product-list.mapper.ts (1)
  • mapProductList (5-26)
packages/framework/src/modules/cms/models/blocks/product-list.model.ts (3)
packages/blocks/product-list/src/api-harmonization/product-list.model.ts (2)
  • Product (57-57)
  • ProductListBlock (7-28)
packages/framework/src/utils/models/filters.ts (3)
  • Filters (1-10)
  • FilterSelect (20-27)
  • FilterDateRange (38-48)
packages/framework/src/modules/products/products.model.ts (1)
  • Products (26-26)
🔇 Additional comments (40)
packages/blocks/product-list/.gitignore (1)

1-57: Standard .gitignore configuration.

This .gitignore file follows conventional patterns for a Node.js/TypeScript package and appropriately excludes build artifacts, dependencies, logs, environment files, IDE configs, and temporary data. The VSCode exceptions (lines 31-36) are sensible for sharing common editor configs in a monorepo setting.

apps/frontend/package.json (1)

9-9: Cross‑platform postbuild script and shx devDependency look good

Switching to shx cp is a nice win for Windows support, and adding shx as a devDependency keeps it scoped to tooling. Please just confirm that whatever runs npm run build in CI/containers installs devDependencies so postbuild doesn’t fail due to a missing shx binary.

Also applies to: 81-81

packages/blocks/product-list/tsconfig.json (1)

1-18: Root TS config and project references look coherent

This root tsconfig.json cleanly extends the shared base and ties together the frontend, API-harmonization, and SDK configs via references, which fits the usual solution‑style pattern for blocks. Please run a tsc --build tsconfig.json from this package once to ensure all three referenced configs build and emit into the expected dist subfolders without complaints.

packages/blocks/product-list/.prettierrc.mjs (1)

1-25: Prettier overrides correctly mirror the three block surfaces

The override mapping of api-harmonization, frontend, and sdk to the shared Prettier configs is consistent with the block’s folder layout and keeps formatting aligned across surfaces. Please ensure your local/editor Prettier setup is picking up this package‑level config (or that the monorepo root config is set to respect it) so contributors get the same formatting automatically.

packages/blocks/product-list/eslint.config.mjs (1)

1-18: ESLint flat config is correctly scoped per surface

Using defineConfig with three entries that extend the API and frontend block configs for their respective src/** subtrees is aligned with how other blocks are wired and with ESLint v9 flat‑config guidance. Based on learnings, this is the intended pattern. Please run the monorepo lint task once to confirm these new globs are picked up as expected.

apps/api-harmonization/src/app.module.ts (1)

42-42: ProductList block registration matches existing block patterns

Importing @o2s/blocks.product-list/api-harmonization and wiring ProductList.Module.register(AppConfig) into the module imports is consistent with how the other blocks are integrated here. Please verify that GET /api/blocks/product-list responds correctly (ideally against the mocked CMS data and Products integration) on at least one of the new /products‑style CMS pages.

Also applies to: 137-137

packages/blocks/product-list/tsconfig.api.json (1)

1-14: API-harmonization TS config aligns with the emitted dist layout

Pointing outDir at ./dist/api-harmonization and constraining baseUrl/include to src/api-harmonization matches the export paths you defined in package.json (e.g. ./api-harmonization). With composite and declarations enabled, this should slot cleanly into the overall project references build. Please confirm that a build of this package produces dist/api-harmonization/api-harmonization/*.js and .d.ts files as expected.

packages/framework/src/modules/cms/cms.model.ts (1)

36-36: New ProductListBlock export is correctly wired

The added ProductListBlock export matches the existing block export pattern and points at the expected ./models/blocks/product-list.model module. No further changes needed.

apps/frontend/src/blocks/renderBlocks.tsx (1)

19-19: ProductListBlock registration in frontend renderer looks consistent

The new ProductList import and 'ProductListBlock' case mirror existing block patterns and align with the updated Modules.Page.Model.Blocks union. Props are forwarded via blockProps as expected.

Also applies to: 133-134

packages/blocks/product-list/src/api-harmonization/product-list.client.ts (1)

1-4: API harmonization client entry is minimal and correct

URL and the Model/Request namespace re-exports are set up as expected for a block client; this matches the usage pattern in sdk/product-list.ts.

packages/blocks/product-list/tsconfig.frontend.json (1)

1-22: Frontend tsconfig aligns with block structure

The extended frontend config, compiler options, and include paths (frontend, api-harmonization product-list files, SDK) look consistent and should support incremental builds without issues.

packages/blocks/product-list/src/sdk/index.ts (1)

1-28: SDK bootstrap and block extension look correct

The SDK is correctly initialized with an environment-derived API_URL and extended to expose blocks.getProductList via productList(internalSdk). The intentional unused Models import and env-based logger options are consistent with the established SDK pattern; just ensure the relevant NEXT_PUBLIC_API_URL* env vars are always set so API_URL! is safe.

apps/api-harmonization/src/modules/page/page.model.ts (1)

18-18: ProductListBlock correctly added to page Blocks union

The new ProductList import and inclusion of ProductList.Model.ProductListBlock['__typename'] in the Blocks union cleanly register the block in the page model and keep typings in sync with the frontend switch on 'ProductListBlock'.

Also applies to: 77-77

packages/blocks/product-list/tsconfig.sdk.json (1)

1-19: SDK tsconfig is consistent with the API/SDK layout

Extending the shared API config, targeting dist/sdk, and including both the SDK source and related api-harmonization files should integrate this SDK cleanly into the existing build graph.

packages/blocks/product-list/src/frontend/ProductList.renderer.tsx (1)

1-28: Invalid use of useLocale in a server-side renderer; use the locale prop instead

As written, ProductListRenderer is a Server Component (no 'use client' directive) but calls useLocale from next-intl, which is only valid in Client Components. Making this file a Client Component would then break, because Client Components cannot import the server component ./ProductList.server.

You already get locale in renderBlocks.tsx and pass it via blockProps, and ProductListRendererProps includes locale. The simplest fix is to treat ProductListRenderer as a pure Server Component, drop useLocale, and use the locale prop:

-import { useLocale } from 'next-intl';
-import React, { Suspense } from 'react';
+import React, { Suspense } from 'react';
@@
-import { ProductListRendererProps } from './ProductList.types';
-
-export const ProductListRenderer: React.FC<ProductListRendererProps> = ({ id, accessToken, routing }) => {
-    const locale = useLocale();
+import { ProductListRendererProps } from './ProductList.types';
+
+export const ProductListRenderer: React.FC<ProductListRendererProps> = ({
+    id,
+    accessToken,
+    locale,
+    routing,
+}) => {
@@
-            <ProductList id={id} accessToken={accessToken} locale={locale} routing={routing} />
+            <ProductList id={id} accessToken={accessToken} locale={locale} routing={routing} />
         </Suspense>
     );
 };

This keeps the component server-side, avoids hook misuse, and leverages the locale resolved in renderBlocks.tsx.

⛔ Skipped due to learnings
Learnt from: marcinkrasowski
Repo: o2sdev/openselfservice PR: 348
File: packages/blocks/notification-summary/src/frontend/NotificationSummary.renderer.tsx:1-15
Timestamp: 2025-11-13T15:40:10.528Z
Learning: In next-intl 3.0+, hook-style APIs like useLocale(), useTranslations(), and useFormatter() can be used in non-async Server Components without the 'use client' directive. The library provides server-optimized implementations automatically. Only async Server Components need to use the await-based APIs like getLocale() from next-intl/server.
packages/integrations/mocked/src/modules/cms/mappers/cms.page.mapper.ts (4)

39-39: LGTM!

The import statement correctly brings in the product list page mocks for all three supported locales.


146-151: LGTM!

The routing implementation correctly maps locale-specific slugs to their corresponding page objects, following the established pattern used for other resource types in this mapper.


278-278: LGTM!

The product list pages are correctly added to all three locale-specific page arrays in getAllPages, maintaining consistency across EN, DE, and PL locales.

Also applies to: 300-300, 322-322


348-348: LGTM!

The product list pages are correctly included in the alternative pages list for all three locales, ensuring proper i18n routing support.

Also applies to: 357-357, 366-366

packages/integrations/mocked/src/modules/cms/cms.service.ts (2)

19-19: LGTM!

The import statement correctly brings in the product list block mapper.


192-194: LGTM!

The getProductListBlock method follows the established pattern used by other block methods in this service, correctly applying responseDelay() to simulate realistic API timing.

packages/blocks/product-list/src/api-harmonization/product-list.request.ts (1)

1-10: LGTM!

The query class correctly implements filtering, sorting, and pagination parameters while properly extending the CMS entry params pattern by omitting locale (which is passed via headers).

packages/integrations/mocked/src/modules/cms/mappers/mocks/pages/product-list.page.ts (3)

3-35: LGTM!

The English product list page mock is correctly structured with appropriate SEO metadata, permissions, and a OneColumnTemplate containing the ProductListBlock.


37-69: LGTM!

The German product list page mock correctly mirrors the English version with properly localized content.


71-103: LGTM!

The Polish product list page mock correctly mirrors the English version with properly localized content.

packages/blocks/product-list/src/sdk/product-list.ts (1)

10-32: LGTM!

The SDK implementation correctly follows the established factory pattern, properly merges headers including optional authorization, and makes a GET request with query parameters.

packages/blocks/product-list/src/frontend/ProductList.server.tsx (1)

8-10: LGTM!

The dynamic import pattern correctly loads the client component with code splitting, following Next.js best practices for server/client component separation.

packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.product-list.mapper.ts (4)

3-92: LGTM!

The English product list block mock is comprehensive, including all necessary fields for filters, pagination, table configuration, and localized labels.


94-183: LGTM!

The German product list block mock correctly mirrors the English version with properly localized content.


185-274: LGTM!

The Polish product list block mock correctly mirrors the English version with properly localized content.


276-287: LGTM!

The mapper function correctly switches on locale with a sensible default fallback to English for unsupported locales.

packages/blocks/product-list/src/api-harmonization/product-list.module.ts (1)

10-31: Code follows established project convention—no changes needed.

All block modules in the codebase consistently use the _config: Framework.ApiConfig parameter pattern with the underscore prefix. This is a TypeScript convention indicating the parameter is intentionally unused. The parameter is kept for API consistency across all block modules.

packages/blocks/product-list/src/frontend/index.ts (1)

1-5: Frontend barrel exports look consistent

Exports for Client, Server, Renderer, and Types align with the corresponding implementation files and follow the existing block barrel pattern. No issues from a type or usage perspective.

packages/blocks/product-list/src/api-harmonization/product-list.mapper.ts (1)

28-49: Product item mapping matches the model expectations

mapProduct correctly projects the core fields (id, sku, name, description, shortDescription, price, image, tags, link) and derives type/category label/value pairs as required by ProductItem. Reusing product.link for both detailsUrl and link is consistent and keeps the model flexible for table vs. card usage.

packages/blocks/product-list/src/frontend/ProductList.types.ts (1)

5-16: Props surface matches component usage and repo conventions

ProductListProps, ProductListPureProps, and ProductListRendererProps line up with how the server/client/renderer components use them, and the Omit<ProductListProps, ''> pattern is consistent with the existing convention in this repo for future-proofing prop omissions. Based on learnings, this is the preferred style here.

packages/blocks/product-list/src/api-harmonization/product-list.model.ts (1)

7-57: API-harmonized models are consistent with CMS and frontend usage

ProductListBlock, ProductList, and ProductItem align well with the CMS block model and the way the client component consumes data (filters, table config, labels, noResults, and product fields). Making noResults.description optional here is a reasonable relaxation while still accepting the stricter CMS data.

packages/blocks/product-list/src/frontend/ProductList.client.tsx (1)

39-55: Disregard this review comment – code is correct for React 19

The codebase uses React 19.2.0, which has native support for async callbacks in startTransition. The pattern startTransition(async () => {...}) is valid, properly typed, and the recommended approach in React 19+.

The review's premise that async callbacks violate TypeScript types is incorrect for React 19. No changes are needed; the code is correct as written.

Likely an incorrect or invalid review comment.

packages/framework/src/modules/cms/models/blocks/product-list.model.ts (3)

1-3: LGTM! Imports are correct.

The imports properly reference the framework's products and utility models needed for the block definition.


7-27: Type alias structure is sound.

The pattern of using Omit and intersection types to specialize the generic DataTable and Filters types for Product entities is correctly implemented. The type aliases follow TypeScript best practices for type composition.


29-46: The mapping implementation is correct—no issues found.

The verification confirms that the framework and API harmonization layers map correctly:

  1. Products structure: The framework's Products type is Pagination.Paginated<Product>, which has data and total properties that map directly to the API's { data: ProductItem[]; total: number } structure. The mapper correctly extracts both via total: products.total and data: products.data.map(...).

  2. Entity types: The framework's Product type is properly converted to the API's ProductItem type through the mapProduct() function, which handles the field transformation explicitly.

The mapping logic at packages/blocks/product-list/src/api-harmonization/product-list.mapper.ts is functioning as intended with no type compatibility issues.

Likely an incorrect or invalid review comment.

@marcinkrasowski marcinkrasowski self-requested a review November 26, 2025 11:54
@Aqil-Ahmad Aqil-Ahmad changed the title feat(product-list): implement product list block with grid plus table view feat(blocks.product-list): implement product list block with grid plus table view Nov 26, 2025
Copy link
Collaborator

@marcinkrasowski marcinkrasowski left a comment

Choose a reason for hiding this comment

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

@Aqil-Ahmad a few comments, but nothing major, looks very good 👍

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (3)
packages/blocks/product-list/src/frontend/ProductList.client.tsx (2)

27-55: Broaden filters state type to match actual filter payload.

initialFilters/filters are typed from { id, offset, limit }, but handleFilter is also used for dynamic fields (e.g. sort, type, category) coming from FiltersSection and pagination. At runtime this works, but TypeScript loses those extra keys, which can make future changes brittle.

Consider introducing an explicit ProductListFilters type that includes id, pagination fields, and dynamic filter keys, and use it for initialFilters, filters, and handleFilter:

-type ViewMode = 'grid' | 'table';
+type ViewMode = 'grid' | 'table';
+type ProductListFilters = {
+    id: string;
+    offset: number;
+    limit: number;
+    // extend with sort, type, category, etc. as needed
+    // sort?: string;
+    // type?: string[];
+    // category?: string[];
+};
@@
-    const initialFilters = {
+    const initialFilters: ProductListFilters = {
         id: component.id,
         offset: 0,
         limit: component.pagination?.limit || 12,
     };
@@
-    const [filters, setFilters] = useState(initialFilters);
+    const [filters, setFilters] = useState<ProductListFilters>(initialFilters);
@@
-    const handleFilter = (data: Partial<typeof initialFilters>) => {
+    const handleFilter = (data: Partial<ProductListFilters>) => {

This keeps the API of handleFilter the same while making the types accurately reflect the shape of the filter object.


100-203: Always show filters/toggle; avoid gating by initialData length.

Currently the whole filters + view toggle + pagination UI is hidden when initialData.length === 0, and the user only sees the static “NoResults” block. If the initial payload is empty (e.g. because of default filters), this prevents users from ever changing filters or paging to find data.

You already handle the no‑results case inside the LoadingOverlay based on data.products.data.length, so you can simplify by removing the outer initialData.length > 0 guard and relying solely on the inner condition:

-    const initialData = component.products.data;
-    const [data, setData] = useState(component);
+    const [data, setData] = useState(component);
@@
-    return (
-        <div className="w-full">
-            {initialData.length > 0 ? (
-                <div className="flex flex-col gap-6">
+    return (
+        <div className="w-full">
+            <div className="flex flex-col gap-6">
@@
-                    <LoadingOverlay isActive={isPending}>
-                        {data.products.data.length ? (
+                    <LoadingOverlay isActive={isPending}>
+                        {data.products.data.length ? (
@@
-                        ) : (
-                            <div className="w-full flex flex-col gap-12 mt-6">
-                                <NoResults title={data.noResults.title} description={data.noResults.description} />
-
-                                <Separator />
-                            </div>
-                        )}
-                    </LoadingOverlay>
-                </div>
-            ) : (
-                <div className="w-full flex flex-col gap-12 mt-6">
-                    <NoResults title={data.noResults.title} description={data.noResults.description} />
-
-                    <Separator />
-                </div>
-            )}
+                        ) : (
+                            <div className="w-full flex flex-col gap-12 mt-6">
+                                <NoResults title={data.noResults.title} description={data.noResults.description} />
+                                <Separator />
+                            </div>
+                        )}
+                    </LoadingOverlay>
+                </div>
             )}
         </div>
     );

This keeps the current behavior for non‑empty results while allowing users to interact with filters and pagination even when the first load returns zero items.

packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.product-list.mapper.ts (1)

55-96: Verify whether __typename should be present on filter items in mocked CMS data.

Each filter item is initialized with __typename: 'FilterSelect'. The framework CMS block models are normalized and avoid __typename at the block level, with discriminators added later in the API‑harmonization layer.

Please double‑check similar mappers (e.g. cms.service-list.mapper.ts) to confirm whether filter items in CMS mocks are also expected to omit __typename and rely on structural typing instead. If so, it would be better to remove __typename here for consistency with normalized CMS models and let the API‑harmonization layer add discriminators where needed.

Based on learnings, CMS block models avoid __typename in the normalized layer.

Also applies to: 160-200, 265-305

📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 67e91cd and e16751b.

📒 Files selected for processing (5)
  • packages/blocks/product-list/src/api-harmonization/product-list.mapper.ts (1 hunks)
  • packages/blocks/product-list/src/api-harmonization/product-list.model.ts (1 hunks)
  • packages/blocks/product-list/src/frontend/ProductList.client.tsx (1 hunks)
  • packages/framework/src/modules/cms/models/blocks/product-list.model.ts (1 hunks)
  • packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.product-list.mapper.ts (1 hunks)
🚧 Files skipped from review as they are similar to previous changes (1)
  • packages/blocks/product-list/src/api-harmonization/product-list.mapper.ts
🧰 Additional context used
🧠 Learnings (3)
📓 Common learnings
Learnt from: marcinkrasowski
Repo: o2sdev/openselfservice PR: 411
File: packages/framework/src/modules/cms/models/blocks/product-list.model.ts:29-46
Timestamp: 2025-11-26T11:57:00.632Z
Learning: In the framework layer (packages/framework/src/modules/cms/models/blocks/*.model.ts), block classes like ProductListBlock should NOT include explicit __typename discriminators. The __typename field is added at the API harmonization layer (packages/blocks/*/src/api-harmonization/*.model.ts) where it's needed for discriminated unions. The framework maintains normalized data models without these discriminators.
📚 Learning: 2025-11-26T11:57:00.632Z
Learnt from: marcinkrasowski
Repo: o2sdev/openselfservice PR: 411
File: packages/framework/src/modules/cms/models/blocks/product-list.model.ts:29-46
Timestamp: 2025-11-26T11:57:00.632Z
Learning: In the framework layer (packages/framework/src/modules/cms/models/blocks/*.model.ts), block classes like ProductListBlock should NOT include explicit __typename discriminators. The __typename field is added at the API harmonization layer (packages/blocks/*/src/api-harmonization/*.model.ts) where it's needed for discriminated unions. The framework maintains normalized data models without these discriminators.

Applied to files:

  • packages/blocks/product-list/src/frontend/ProductList.client.tsx
  • packages/blocks/product-list/src/api-harmonization/product-list.model.ts
  • packages/framework/src/modules/cms/models/blocks/product-list.model.ts
  • packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.product-list.mapper.ts
📚 Learning: 2025-11-14T14:24:34.907Z
Learnt from: marcinkrasowski
Repo: o2sdev/openselfservice PR: 357
File: packages/blocks/ticket-summary/src/frontend/TicketSummary.types.ts:14-16
Timestamp: 2025-11-14T14:24:34.907Z
Learning: In the openselfservice repository, the pattern `Omit<PropsType, ''>` in TypeScript type definitions is intentionally used as a template for future prop omissions, even though it currently does nothing. This convention is preferred for consistency across blocks, making it easier to add omissions when needed later.

Applied to files:

  • packages/blocks/product-list/src/frontend/ProductList.client.tsx
🧬 Code graph analysis (3)
packages/blocks/product-list/src/api-harmonization/product-list.model.ts (5)
packages/framework/src/utils/models/filters.ts (1)
  • Filters (1-10)
packages/framework/src/modules/products/products.model.ts (1)
  • Products (26-26)
packages/integrations/strapi-cms/generated/strapi.ts (1)
  • Mapping (2142-2149)
packages/framework/src/utils/models/price.ts (1)
  • Price (3-7)
packages/framework/src/utils/models/media.ts (1)
  • Media (1-7)
packages/framework/src/modules/cms/models/blocks/product-list.model.ts (3)
packages/blocks/product-list/src/api-harmonization/product-list.model.ts (2)
  • ProductListBlock (7-29)
  • Product (58-58)
packages/integrations/strapi-cms/generated/strapi.ts (1)
  • Mapping (2142-2149)
packages/framework/src/utils/models/filters.ts (1)
  • Filters (1-10)
packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.product-list.mapper.ts (2)
packages/blocks/product-list/src/api-harmonization/product-list.model.ts (1)
  • ProductListBlock (7-29)
packages/framework/src/modules/cms/models/blocks/product-list.model.ts (1)
  • ProductListBlock (5-22)
🔇 Additional comments (2)
packages/framework/src/modules/cms/models/blocks/product-list.model.ts (1)

5-22: CMS ProductListBlock model looks consistent with existing patterns.

The block shape (table, fieldMapping, pagination, filters, labels, optional detailsLabel) matches other CMS block models and correctly omits __typename in the normalized framework layer, with noResults.description marked optional.

No changes needed here.

Based on learnings, the absence of __typename in this framework model is correct.

packages/blocks/product-list/src/api-harmonization/product-list.model.ts (1)

7-29: API-harmonized ProductList models align with framework and frontend usage.

ProductListBlock and ProductItem include the expected fields (discriminator, filters, pagination, table, mapping, products, labels) and match the shapes consumed by the client component and CMS model snippets. I don’t see structural or typing issues here.

Also applies to: 36-56

@Aqil-Ahmad
Copy link
Contributor Author

thank you @marcinkrasowski for the review!

i've resolved most of the comments. but i will add the storybook in a separate commit.
i'll push the updates shortly.

Copy link

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 2

🧹 Nitpick comments (2)
packages/blocks/product-list/src/frontend/ProductList.client.stories.tsx (1)

19-303: Inline args are comprehensive; consider extracting fixtures and local images

The args object is nicely realistic (filters, pagination, table config, labels, products, alt text) and should exercise both grid and table views well.

To keep the story file lighter and easier to maintain, consider:

  • Extracting the large args object to a shared fixture (e.g., productListMockArgs) that can be reused across stories/tests.
  • Optionally replacing external raw.githubusercontent.com image URLs with locally served static assets to avoid network flakiness in Storybook.

Not required for correctness, but it would improve maintainability and resilience.

packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.product-list.mapper.ts (1)

318-329: Consider narrowing the locale type for stronger type‑safety.

mapProductListBlock currently accepts locale: string but only handles 'en' | 'de' | 'pl'. Narrowing this to a string union (or a shared Locale type if available in the framework) will catch invalid locales at compile time.

For example:

-export const mapProductListBlock = (locale: string): CMS.Model.ProductListBlock.ProductListBlock => {
+export const mapProductListBlock = (
+    locale: 'en' | 'de' | 'pl',
+): CMS.Model.ProductListBlock.ProductListBlock => {
📜 Review details

Configuration used: CodeRabbit UI

Review profile: CHILL

Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between e16751b and 0b35579.

📒 Files selected for processing (2)
  • packages/blocks/product-list/src/frontend/ProductList.client.stories.tsx (1 hunks)
  • packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.product-list.mapper.ts (1 hunks)
🧰 Additional context used
🧠 Learnings (1)
📚 Learning: 2025-11-26T11:57:00.632Z
Learnt from: marcinkrasowski
Repo: o2sdev/openselfservice PR: 411
File: packages/framework/src/modules/cms/models/blocks/product-list.model.ts:29-46
Timestamp: 2025-11-26T11:57:00.632Z
Learning: In the framework layer (packages/framework/src/modules/cms/models/blocks/*.model.ts), block classes like ProductListBlock should NOT include explicit __typename discriminators. The __typename field is added at the API harmonization layer (packages/blocks/*/src/api-harmonization/*.model.ts) where it's needed for discriminated unions. The framework maintains normalized data models without these discriminators.

Applied to files:

  • packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.product-list.mapper.ts
🧬 Code graph analysis (1)
packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.product-list.mapper.ts (2)
packages/framework/src/modules/cms/models/blocks/product-list.model.ts (1)
  • ProductListBlock (5-22)
packages/blocks/product-list/src/api-harmonization/product-list.model.ts (1)
  • ProductListBlock (7-29)
🪛 Gitleaks (8.29.1)
packages/blocks/product-list/src/frontend/ProductList.client.stories.tsx

[high] 18-18: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)

🔇 Additional comments (2)
packages/blocks/product-list/src/frontend/ProductList.client.stories.tsx (1)

1-13: Solid Storybook meta and typing

Use of satisfies Meta<typeof ProductListPure> plus StoryObj<typeof meta> is idiomatic and keeps the story strongly typed against the component props. No issues here.

packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.product-list.mapper.ts (1)

55-95: Based on the web search results and the learnings provided, I can now assess the original review comment:

The original review comment contains a fundamental misconception. The learnings you provided state that the framework layer (e.g., packages/framework/.../product-list.model.ts) should NOT include __typename discriminators—which is correct. However, the file under review is a mapper in the mocked integration layer (packages/integrations/mocked/.../cms.product-list.mapper.ts).

Per GraphQL best practices (confirmed via web search), mappers and harmonization layers are the canonical place to add __typename for discriminated unions. This is intentional and necessary for client-side type narrowing and GraphQL tooling.

The original review misapplies the learnings to the wrong architectural layer.

Since the review comment is also incomplete (it ends abruptly with placeholder tags and lacks a coherent final recommendation), and since I cannot access the codebase to verify the secondary concerns (PL label mismatch, locale typing), here is my final assessment:


The __typename field on filter items is correct for the mapper layer and follows GraphQL best practices for discriminated unions.

The learnings correctly state that the framework layer should avoid __typename discriminators to maintain normalized data models. However, mappers operate at the API harmonization layer, where __typename is intentionally added to support client-side GraphQL type discrimination and tooling. This separation of concerns is by design: framework models are normalized; mappers add __typename for API consumption.

The secondary concerns raised in the original comment (PL label consistency, locale typing narrowness) cannot be verified without codebase access.

Likely an incorrect or invalid review comment.

Comment on lines +15 to +18
args: {
locale: 'en',
accessToken:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSmFuZSBEb2UiLCJlbWFpbCI6ImphbmVAZXhhbXBsZS5jb20iLCJyb2xlIjoic2VsZnNlcnZpY2Vfb3JnX2FkbWluIiwiY3VzdG9tZXIiOnsiaWQiOiJjdXN0LTAwMSIsInJvbGVzIjpbInNlbGZzZXJ2aWNlX29yZ191c2VyIiwic2VsZnNlcnZpY2Vfb3JnX3VzZXIiLCJzZWxmc2VydmljZV9vcmdfYWRtaW4iXSwibmFtZSI6IkFjbWUgQ29ycG9yYXRpb24ifSwiaWF0IjoxNzU2MzI0ODI5fQ.i-ofzMm1drdeK2_-ORFrv4YZZwadD_P-URxF_cMlkV4',
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Remove hard‑coded JWT access token from the repo

The accessToken prop currently embeds what looks like a full JWT, which is exactly what Gitleaks flagged. Even in Storybook, committing realistic tokens is a security/compliance risk and can confuse future scanners.

Replace this with a clearly fake placeholder or mock value (and rotate/revoke the real token if it ever existed):

-        accessToken:
-            'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSmFuZSBEb2UiLCJlbWFpbCI6ImphbmVAZXhhbXBsZS5jb20iLCJyb2xlIjoic2VsZnNlcnZpY2Vfb3JnX2FkbWluIiwiY3VzdG9tZXIiOnsiaWQiOiJjdXN0LTAwMSIsInJvbGVzIjpbInNlbGZzZXJ2aWNlX29yZ191c2VyIiwic2VsZnNlcnZpY2Vfb3JnX3VzZXIiLCJzZWxmc2VydmljZV9vcmdfYWRtaW4iXSwibmFtZSI6IkFjbWUgQ29ycG9yYXRpb24ifSwiaWF0IjoxNzU2MzI0ODI5fQ.i-ofzMm1drdeK2_-ORFrv4YZZwadD_P-URxF_cMlkV4',
+        // Storybook-only dummy token; not a real credential
+        accessToken: 'example-access-token',

If the component doesn’t actually require a valid token for rendering in Storybook, you can also consider making the prop optional or using undefined here.

📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
args: {
locale: 'en',
accessToken:
'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSmFuZSBEb2UiLCJlbWFpbCI6ImphbmVAZXhhbXBsZS5jb20iLCJyb2xlIjoic2VsZnNlcnZpY2Vfb3JnX2FkbWluIiwiY3VzdG9tZXIiOnsiaWQiOiJjdXN0LTAwMSIsInJvbGVzIjpbInNlbGZzZXJ2aWNlX29yZ191c2VyIiwic2VsZnNlcnZpY2Vfb3JnX3VzZXIiLCJzZWxmc2VydmljZV9vcmdfYWRtaW4iXSwibmFtZSI6IkFjbWUgQ29ycG9yYXRpb24ifSwiaWF0IjoxNzU2MzI0ODI5fQ.i-ofzMm1drdeK2_-ORFrv4YZZwadD_P-URxF_cMlkV4',
args: {
locale: 'en',
// Storybook-only dummy token; not a real credential
accessToken: 'example-access-token',
🧰 Tools
🪛 Gitleaks (8.29.1)

[high] 18-18: Uncovered a JSON Web Token, which may lead to unauthorized access to web applications and sensitive user data.

(jwt)

🤖 Prompt for AI Agents
In packages/blocks/product-list/src/frontend/ProductList.client.stories.tsx
around lines 15 to 18, the story embeds a real-looking JWT in the accessToken
arg; remove the hard-coded token and replace it with a non-sensitive placeholder
(e.g. 'FAKE_ACCESS_TOKEN') or set the prop to undefined, or update the
component/story to make accessToken optional for Storybook rendering; if this
token was ever valid ensure it is revoked/rotated outside of this change.

Comment on lines +224 to +234
SOFTWARE: 'Oprogramowanie',
TOOLS: 'Narzędzia',
HARDWARE: 'Sprzęt',
MEASUREMENT: 'Pomiar',
CLOUD: 'Chmura',
SUPPORT: 'Wsparcie',
SUBSCRIPTION: 'Subskrypcja',
WARRANTY: 'Gwarancja',
MAINTENANCE: 'Konserwacja',
TRAINING: 'Szkolenie',
},
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Align Polish MAINTENANCE category label between mapping and filters.

In the PL block, fieldMapping.category.MAINTENANCE is "Konserwacja", while the corresponding filter option label is "Utrzymanie". This is likely unintentional and may confuse users; make them consistent (similar to how DE SUBSCRIPTION was aligned).

For example, you could align the filter label with the mapping:

-                    { label: 'Utrzymanie', value: 'MAINTENANCE' },
+                    { label: 'Konserwacja', value: 'MAINTENANCE' },

Also applies to: 293-303

🤖 Prompt for AI Agents
In
packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.product-list.mapper.ts
around lines 224-234 (and similarly review lines 293-303), the Polish labels for
the MAINTENANCE category are inconsistent between the fieldMapping (Konserwacja)
and the filter options (Utrzymanie); update the filter option label(s) to match
the mapping by changing "Utrzymanie" to "Konserwacja" wherever the PL filter
labels for MAINTENANCE appear so both mapping and filters use the same Polish
term.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Feature] product list block

2 participants