From b5158848e8e36d597e2bd578fe62678b14932d11 Mon Sep 17 00:00:00 2001 From: Michal Nowak Date: Wed, 5 Nov 2025 13:28:58 +0100 Subject: [PATCH 1/6] feat(ui): add showChart property to orders summary block and update related components --- .../orders-summary.mapper.ts | 1 + .../api-harmonization/orders-summary.model.ts | 1 + .../frontend/OrdersSummary.client.stories.tsx | 1 + .../src/frontend/OrdersSummary.client.tsx | 92 +++++++++++++------ .../cms/models/blocks/orders-summary.model.ts | 1 + .../blocks/cms.orders-summary.mapper.ts | 5 +- .../strapi-cms/generated/strapi.ts | 1 + .../fragments/blocks/OrdersSummary.graphql | 1 + .../blocks/cms.orders-summary.mapper.ts | 1 + 9 files changed, 76 insertions(+), 28 deletions(-) diff --git a/packages/blocks/orders-summary/src/api-harmonization/orders-summary.mapper.ts b/packages/blocks/orders-summary/src/api-harmonization/orders-summary.mapper.ts index 84b0d6af2..9275a7165 100644 --- a/packages/blocks/orders-summary/src/api-harmonization/orders-summary.mapper.ts +++ b/packages/blocks/orders-summary/src/api-harmonization/orders-summary.mapper.ts @@ -61,6 +61,7 @@ export const mapOrdersSummary = ( title: cms.chart.title, data: getChartData(ordersPrevious, ordersCurrent, range, diff, locale), legend: cms.chart.legend, + showChart: cms.chart.showChart, }, noResults: cms.noResults, ranges: cms.ranges, diff --git a/packages/blocks/orders-summary/src/api-harmonization/orders-summary.model.ts b/packages/blocks/orders-summary/src/api-harmonization/orders-summary.model.ts index e5a4f3a10..ec342f669 100644 --- a/packages/blocks/orders-summary/src/api-harmonization/orders-summary.model.ts +++ b/packages/blocks/orders-summary/src/api-harmonization/orders-summary.model.ts @@ -33,6 +33,7 @@ export class OrdersSummaryBlock extends ApiModels.Block.Block { prev: string; current: string; }; + showChart?: boolean; }; ranges!: CMS.Model.OrdersSummaryBlock.OrdersSummaryBlock['ranges']; noResults!: CMS.Model.OrdersSummaryBlock.OrdersSummaryBlock['noResults']; diff --git a/packages/blocks/orders-summary/src/frontend/OrdersSummary.client.stories.tsx b/packages/blocks/orders-summary/src/frontend/OrdersSummary.client.stories.tsx index fc9612588..91879a365 100644 --- a/packages/blocks/orders-summary/src/frontend/OrdersSummary.client.stories.tsx +++ b/packages/blocks/orders-summary/src/frontend/OrdersSummary.client.stories.tsx @@ -82,6 +82,7 @@ export const Default: Story = { prev: 'Previous period', current: 'Current period', }, + showChart: true, }, noResults: { title: "So far, there's nothing here", diff --git a/packages/blocks/orders-summary/src/frontend/OrdersSummary.client.tsx b/packages/blocks/orders-summary/src/frontend/OrdersSummary.client.tsx index 3525ca6b4..ff0d121d0 100644 --- a/packages/blocks/orders-summary/src/frontend/OrdersSummary.client.tsx +++ b/packages/blocks/orders-summary/src/frontend/OrdersSummary.client.tsx @@ -125,20 +125,70 @@ export const OrdersSummaryPure: React.FC> = ({ )} -
-
- - - - } - description={} - icon={data.totalValue.icon} - /> - -
+
+ {data.chart.showChart ? ( + <> +
+ + + + } + description={} + icon={data.totalValue.icon} + /> + +
+ + + + } + description={} + icon={data.averageValue.icon} + /> + + {data.averageNumber.value} + + } + description={} + icon={data.averageNumber.icon} + /> +
+
+ +
+ {data.chart.title} + + +
+
+ + ) : ( +
+ + + + } + description={} + icon={data.totalValue.icon} + /> > = ({ icon={data.averageNumber.icon} />
-
- - -
- {data.chart.title} - - -
-
+ )}
diff --git a/packages/framework/src/modules/cms/models/blocks/orders-summary.model.ts b/packages/framework/src/modules/cms/models/blocks/orders-summary.model.ts index e130f29d2..98fd6f32f 100644 --- a/packages/framework/src/modules/cms/models/blocks/orders-summary.model.ts +++ b/packages/framework/src/modules/cms/models/blocks/orders-summary.model.ts @@ -17,6 +17,7 @@ export class OrdersSummaryBlock extends Block.Block { export class OrdersChart { title!: string; legend!: ChartLegend; + showChart?: boolean; } export class ChartLegend { diff --git a/packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.orders-summary.mapper.ts b/packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.orders-summary.mapper.ts index 6c1e54ada..35ffa717c 100644 --- a/packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.orders-summary.mapper.ts +++ b/packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.orders-summary.mapper.ts @@ -22,6 +22,7 @@ const MOCK_ORDER_LIST_BLOCK_EN: CMS.Model.OrdersSummaryBlock.OrdersSummaryBlock prev: 'Previous period', current: 'Current period', }, + showChart: true, }, noResults: { title: "So far, there's nothing here", @@ -69,6 +70,7 @@ const MOCK_ORDER_LIST_BLOCK_DE: CMS.Model.OrdersSummaryBlock.OrdersSummaryBlock prev: 'Vorheriger Zeitraum', current: 'Aktueller Zeitraum', }, + showChart: true, }, noResults: { title: 'Bisher gibt es hier nichts', @@ -111,11 +113,12 @@ const MOCK_ORDER_LIST_BLOCK_PL: CMS.Model.OrdersSummaryBlock.OrdersSummaryBlock icon: 'Package', }, chart: { - title: 'Liczba zamówień', + title: 'Liczba zamówień123', legend: { prev: 'Poprzedni okres', current: 'Obecny okres', }, + showChart: true, }, noResults: { title: 'Jak dotąd nie ma tu nic', diff --git a/packages/integrations/strapi-cms/generated/strapi.ts b/packages/integrations/strapi-cms/generated/strapi.ts index e6ad88aa1..8bd494b6e 100644 --- a/packages/integrations/strapi-cms/generated/strapi.ts +++ b/packages/integrations/strapi-cms/generated/strapi.ts @@ -10961,6 +10961,7 @@ export type GetComponentQuery = { chartTitle: string; chartPreviousPeriodLabel: string; chartCurrentPeriodLabel: string; + showChart?: boolean; ranges?: Array<{ id: string; label: string; diff --git a/packages/integrations/strapi-cms/src/modules/cms/graphql/fragments/blocks/OrdersSummary.graphql b/packages/integrations/strapi-cms/src/modules/cms/graphql/fragments/blocks/OrdersSummary.graphql index a9d611eaa..ed98814b0 100644 --- a/packages/integrations/strapi-cms/src/modules/cms/graphql/fragments/blocks/OrdersSummary.graphql +++ b/packages/integrations/strapi-cms/src/modules/cms/graphql/fragments/blocks/OrdersSummary.graphql @@ -6,6 +6,7 @@ fragment OrdersSummaryComponent on ComponentComponentsOrdersSummary { chartTitle chartPreviousPeriodLabel chartCurrentPeriodLabel + showChart ranges { id label diff --git a/packages/integrations/strapi-cms/src/modules/cms/mappers/blocks/cms.orders-summary.mapper.ts b/packages/integrations/strapi-cms/src/modules/cms/mappers/blocks/cms.orders-summary.mapper.ts index ccfeb6104..19c6f0e34 100644 --- a/packages/integrations/strapi-cms/src/modules/cms/mappers/blocks/cms.orders-summary.mapper.ts +++ b/packages/integrations/strapi-cms/src/modules/cms/mappers/blocks/cms.orders-summary.mapper.ts @@ -35,6 +35,7 @@ export const mapOrdersSummaryBlock = (data: GetComponentQuery): CMS.Model.Orders prev: component.chartPreviousPeriodLabel, current: component.chartCurrentPeriodLabel, }, + showChart: component.showChart, }, ranges: component.ranges?.map((range) => ({ label: range.label, From 35e2d6ba5657ac97ecff5d92e210d7e7c3174761 Mon Sep 17 00:00:00 2001 From: Michal Nowak Date: Wed, 5 Nov 2025 15:59:02 +0100 Subject: [PATCH 2/6] feat(ui): enhance Payments Summary block with chart support and layout options --- .../payments-summary.mapper.ts | 83 +++++- .../payments-summary.model.ts | 25 +- .../PaymentsSummary.client.stories.tsx | 131 ++++++++- .../src/frontend/PaymentsSummary.client.tsx | 264 +++++++++++++----- .../models/blocks/payments-summary.model.ts | 16 +- .../blocks/cms.orders-summary.mapper.ts | 2 +- .../blocks/cms.payments-summary.mapper.ts | 11 + .../mappers/mocks/pages/invoice-list.page.ts | 33 +-- .../strapi-cms/generated/strapi.ts | 10 + .../fragments/blocks/PaymentsSummary.graphql | 10 + .../blocks/cms.payments-summary.mapper.ts | 12 + 11 files changed, 480 insertions(+), 117 deletions(-) diff --git a/packages/blocks/payments-summary/src/api-harmonization/payments-summary.mapper.ts b/packages/blocks/payments-summary/src/api-harmonization/payments-summary.mapper.ts index b840c0982..73f7f4d6b 100644 --- a/packages/blocks/payments-summary/src/api-harmonization/payments-summary.mapper.ts +++ b/packages/blocks/payments-summary/src/api-harmonization/payments-summary.mapper.ts @@ -6,7 +6,7 @@ import { Utils } from '@o2s/utils.api-harmonization'; import { Models } from '@o2s/framework/modules'; -import { PaymentsSummaryBlock } from './payments-summary.model'; +import { BarData, PaymentsSummaryBlock } from './payments-summary.model'; export const mapPaymentsSummary = ( cms: CMS.Model.PaymentsSummaryBlock.PaymentsSummaryBlock, @@ -33,11 +33,14 @@ export const mapPaymentsSummary = ( return acc + invoice.totalToBePaid.value; }, 0); - return { + const result: PaymentsSummaryBlock = { __typename: 'PaymentsSummaryBlock', id: cms.id, currency: currency, - overdue: { + }; + + if (cms.overdue) { + result.overdue = { title: cms.overdue.title, link: cms.overdue.link, description: isOverdue @@ -48,13 +51,79 @@ export const mapPaymentsSummary = ( value: { value: Utils.Price.checkNegativeValue({ value: overdueAmount, currency }).value, currency }, isOverdue: isOverdue, icon: cms.overdue.icon, - }, - toBePaid: { + }; + } + + if (cms.toBePaid) { + result.toBePaid = { title: cms.toBePaid.title, icon: cms.toBePaid.icon, description: toBePaidAmount > 0 ? cms.toBePaid?.message : cms.toBePaid?.altMessage, link: cms.toBePaid.link, value: { value: Utils.Price.checkNegativeValue({ value: toBePaidAmount, currency }).value, currency }, - }, - }; + }; + } + + if (cms.layout) { + result.layout = cms.layout; + } + + if (cms.chart) { + result.chart = { + title: cms.chart.title, + labels: { + topSegment: cms.chart.topSegment, + middleSegment: cms.chart.middleSegment, + bottomSegment: cms.chart.bottomSegment, + total: cms.chart.total, + }, + chartData: mapChartData(invoices.data, _locale, cms.chart.monthsToShow), + showChart: cms.chart.showChart, + monthsToShow: cms.chart.monthsToShow, + }; + } + + return result; +}; + +const mapChartData = (data: Invoices.Model.Invoice[], locale: string, monthsToShow: number = 6): BarData[] => { + const now = new Date(); + const monthsToShowAgo = new Date(now.getFullYear(), now.getMonth() - monthsToShow - 1, 1); + + const months = Array.from({ length: monthsToShow }, (_, i) => { + const date = new Date(now.getFullYear(), now.getMonth() - i, 1); + return { + month: date.toLocaleString(locale, { month: 'short' }), + topSegment: 0, + middleSegment: 0, + bottomSegment: 0, + total: 0, + date: date, + }; + }).reverse(); + + // Sum up invoice amounts for each month + data.forEach((invoice) => { + const invoiceDate = new Date(invoice.issuedDate); + if (invoiceDate >= monthsToShowAgo) { + const month = months.find( + (m) => + m.date.getMonth() === invoiceDate.getMonth() && m.date.getFullYear() === invoiceDate.getFullYear(), + ); + if (month) { + month.topSegment += invoice.paymentStatus === 'PAYMENT_PAST_DUE' ? invoice.totalAmountDue.value : 0; + month.middleSegment += invoice.paymentStatus === 'PAYMENT_DUE' ? invoice.totalAmountDue.value : 0; + month.bottomSegment += invoice.paymentStatus === 'PAYMENT_COMPLETE' ? invoice.totalAmountDue.value : 0; + month.total += invoice.totalAmountDue.value; + } + } + }); + + return months.map((month) => ({ + month: month.month, + topSegment: month.topSegment.toFixed(2), + middleSegment: month.middleSegment.toFixed(2), + bottomSegment: month.bottomSegment.toFixed(2), + total: month.total.toFixed(2), + })); }; diff --git a/packages/blocks/payments-summary/src/api-harmonization/payments-summary.model.ts b/packages/blocks/payments-summary/src/api-harmonization/payments-summary.model.ts index 387599829..dfee0efdd 100644 --- a/packages/blocks/payments-summary/src/api-harmonization/payments-summary.model.ts +++ b/packages/blocks/payments-summary/src/api-harmonization/payments-summary.model.ts @@ -5,7 +5,7 @@ import { Invoices, Models } from '@o2s/framework/modules'; export class PaymentsSummaryBlock extends ApiModels.Block.Block { __typename!: 'PaymentsSummaryBlock'; currency!: Invoices.Model.Invoice['currency']; - overdue!: { + overdue?: { title: string; icon?: string; value: Models.Price.Price; @@ -17,7 +17,7 @@ export class PaymentsSummaryBlock extends ApiModels.Block.Block { }; isOverdue: boolean; }; - toBePaid!: { + toBePaid?: { title: string; icon?: string; value: Models.Price.Price; @@ -28,4 +28,25 @@ export class PaymentsSummaryBlock extends ApiModels.Block.Block { icon?: string; }; }; + layout?: 'vertical' | 'horizontal'; + chart?: { + title?: string; + labels: { + topSegment: string; + middleSegment: string; + bottomSegment: string; + total: string; + }; + chartData: BarData[]; + showChart?: boolean; + monthsToShow?: number; + }; +} + +export class BarData { + month!: string; + topSegment!: string; + middleSegment!: string; + bottomSegment!: string; + total!: string; } diff --git a/packages/blocks/payments-summary/src/frontend/PaymentsSummary.client.stories.tsx b/packages/blocks/payments-summary/src/frontend/PaymentsSummary.client.stories.tsx index e72bf8b8c..8733a255c 100644 --- a/packages/blocks/payments-summary/src/frontend/PaymentsSummary.client.stories.tsx +++ b/packages/blocks/payments-summary/src/frontend/PaymentsSummary.client.stories.tsx @@ -11,22 +11,28 @@ export default meta; type Story = StoryObj; +const baseRouting = { + locales: ['en', 'de', 'pl'], + defaultLocale: 'en', + pathnames: { + '/login': { + en: '/sign-in', + de: '/einloggen', + pl: '/logowanie', + }, + }, +}; + +const baseAccessToken = + 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSmFuZSBEb2UiLCJlbWFpbCI6ImphbmVAZXhhbXBsZS5jb20iLCJyb2xlIjoic2VsZnNlcnZpY2Vfb3JnX2FkbWluIiwiY3VzdG9tZXIiOnsiaWQiOiJjdXN0LTAwMSIsInJvbGVzIjpbInNlbGZzZXJ2aWNlX29yZ191c2VyIiwic2VsZnNlcnZpY2Vfb3JnX3VzZXIiLCJzZWxmc2VydmljZV9vcmdfYWRtaW4iXSwibmFtZSI6IkFjbWUgQ29ycG9yYXRpb24ifSwiaWF0IjoxNzU2MzI0NTg0fQ.wFAXi1DbgN67z8xQcqZdGz9YeAolbim3lecVIzV2rv0'; + export const Default: Story = { args: { - routing: { - locales: ['en', 'de', 'pl'], - defaultLocale: 'en', - pathnames: { - '/login': { - en: '/sign-in', - de: '/einloggen', - pl: '/logowanie', - }, - }, - }, + routing: baseRouting, __typename: 'PaymentsSummaryBlock', id: 'payments-summary-1', currency: 'EUR', + layout: 'vertical', overdue: { title: 'Overdue', link: { @@ -44,20 +50,115 @@ export const Default: Story = { }, toBePaid: { title: 'To be paid', - icon: 'CreditCard', + link: { + label: 'Pay online', + icon: 'ArrowUpRight', + url: '', + }, description: 'New and overdue', + value: { + value: 1234.56, + currency: 'EUR', + }, + icon: 'CreditCard', + }, + accessToken: baseAccessToken, + locale: 'en', + }, +}; + +export const WithChart: Story = { + args: { + routing: baseRouting, + __typename: 'PaymentsSummaryBlock', + id: 'payments-summary-7', + currency: 'EUR', + layout: 'vertical', + overdue: { + title: 'Overdue', + link: { + label: 'Pay online', + icon: 'ArrowUpRight', + url: '', + }, + description: '599 days overdue', + value: { + value: 5544.828051951577, + currency: 'EUR', + }, + isOverdue: true, + icon: 'ThumbsUp', + }, + toBePaid: { + title: 'To be paid', link: { label: 'Pay online', icon: 'ArrowUpRight', url: '', }, + description: 'New and overdue', value: { - value: 1674.6002166383103, + value: 1234.56, currency: 'EUR', }, + icon: 'CreditCard', + }, + chart: { + title: '6-months history', + labels: { + topSegment: 'Overdue', + middleSegment: 'To be paid', + bottomSegment: 'Paid', + total: 'Total', + }, + chartData: [ + { + month: 'Jan', + topSegment: '100.00', + middleSegment: '200.00', + bottomSegment: '300.00', + total: '600.00', + }, + { + month: 'Feb', + topSegment: '150.00', + middleSegment: '250.00', + bottomSegment: '350.00', + total: '750.00', + }, + { + month: 'Mar', + topSegment: '120.00', + middleSegment: '220.00', + bottomSegment: '320.00', + total: '660.00', + }, + { + month: 'Apr', + topSegment: '180.00', + middleSegment: '280.00', + bottomSegment: '380.00', + total: '840.00', + }, + { + month: 'May', + topSegment: '200.00', + middleSegment: '300.00', + bottomSegment: '400.00', + total: '900.00', + }, + { + month: 'Jun', + topSegment: '160.00', + middleSegment: '260.00', + bottomSegment: '360.00', + total: '780.00', + }, + ], + showChart: true, + monthsToShow: 6, }, - accessToken: - 'eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJuYW1lIjoiSmFuZSBEb2UiLCJlbWFpbCI6ImphbmVAZXhhbXBsZS5jb20iLCJyb2xlIjoic2VsZnNlcnZpY2Vfb3JnX2FkbWluIiwiY3VzdG9tZXIiOnsiaWQiOiJjdXN0LTAwMSIsInJvbGVzIjpbInNlbGZzZXJ2aWNlX29yZ191c2VyIiwic2VsZnNlcnZpY2Vfb3JnX3VzZXIiLCJzZWxmc2VydmljZV9vcmdfYWRtaW4iXSwibmFtZSI6IkFjbWUgQ29ycG9yYXRpb24ifSwiaWF0IjoxNzU2MzI0NTg0fQ.wFAXi1DbgN67z8xQcqZdGz9YeAolbim3lecVIzV2rv0', + accessToken: baseAccessToken, locale: 'en', }, }; diff --git a/packages/blocks/payments-summary/src/frontend/PaymentsSummary.client.tsx b/packages/blocks/payments-summary/src/frontend/PaymentsSummary.client.tsx index 78f528605..ab823f33c 100644 --- a/packages/blocks/payments-summary/src/frontend/PaymentsSummary.client.tsx +++ b/packages/blocks/payments-summary/src/frontend/PaymentsSummary.client.tsx @@ -1,6 +1,7 @@ 'use client'; import { useTranslations } from 'next-intl'; +import dynamic from 'next/dynamic'; import React from 'react'; import { cn } from '@o2s/ui/lib/utils'; @@ -12,88 +13,219 @@ import { RichText } from '@o2s/ui/components/RichText'; import { TooltipHover } from '@o2s/ui/components/TooltipHover'; import { Button } from '@o2s/ui/elements/button'; +import { Card } from '@o2s/ui/elements/card'; import { Typography } from '@o2s/ui/elements/typography'; import { PaymentsSummaryPureProps } from './PaymentsSummary.types'; +const StackedBarChart = dynamic(() => + import('@o2s/ui/components/Chart/StackedBarChart').then((module) => module.StackedBarChart), +); + export const PaymentsSummaryPure: React.FC = ({ routing, ...component }) => { - const { overdue, toBePaid } = component; + const { overdue, toBePaid, layout, chart } = component; const t = useTranslations(); // If navigation is needed, use createNavigation(routing) as in other blocks // const { Link: LinkComponent } = createNavigation(routing); + if (!overdue && !toBePaid && !chart?.showChart) { + return null; + } + + const showChart = chart?.showChart ?? false; + const cardsLayout = layout === 'horizontal' ? 'flex-col md:flex-row' : 'flex-col'; + return ( -
- - - - } - description={ -
- +
+ {showChart ? ( + <> +
+ {overdue && ( + + + + } + description={ +
+ +
+ } + icon={ + overdue.isOverdue ? ( + + ) : ( + overdue.icon + ) + } + button={ + overdue.isOverdue && + overdue.link && ( + ( + + )} + content={

{t('general.comingSoon')}

} + /> + ) + } + /> + )} + {toBePaid && ( + + + + } + description={toBePaid.description} + icon={toBePaid.icon} + button={ + toBePaid.value.value > 0 && + toBePaid.link && ( + ( + + )} + content={

{t('general.comingSoon')}

} + /> + ) + } + /> + )}
- } - icon={ - overdue.isOverdue ? : overdue.icon - } - button={ - overdue.isOverdue && - overdue.link && ( - ( - - )} - content={

{t('general.comingSoon')}

} + + + } + description={ +
+ +
+ } + icon={ + overdue.isOverdue ? ( + + ) : ( + overdue.icon + ) + } + button={ + overdue.isOverdue && + overdue.link && ( + ( + + )} + content={

{t('general.comingSoon')}

} + /> + ) + } /> - ) - } - /> - - - - - } - description={toBePaid.description} - icon={toBePaid.icon} - button={ - toBePaid.value.value > 0 && - toBePaid.link && ( - ( - - )} - content={

{t('general.comingSoon')}

} + )} + {toBePaid && ( + + + + } + description={toBePaid.description} + icon={toBePaid.icon} + button={ + toBePaid.value.value > 0 && + toBePaid.link && ( + ( + + )} + content={

{t('general.comingSoon')}

} + /> + ) + } /> - ) - } - /> + )} + + )}
); }; diff --git a/packages/framework/src/modules/cms/models/blocks/payments-summary.model.ts b/packages/framework/src/modules/cms/models/blocks/payments-summary.model.ts index 278ea9f50..674e82368 100644 --- a/packages/framework/src/modules/cms/models/blocks/payments-summary.model.ts +++ b/packages/framework/src/modules/cms/models/blocks/payments-summary.model.ts @@ -1,6 +1,18 @@ import { Block, InfoCard } from '@/utils/models'; +export class PaymentsSummaryChart { + title?: string; + topSegment!: string; + middleSegment!: string; + bottomSegment!: string; + total!: string; + showChart?: boolean; + monthsToShow?: number; +} + export class PaymentsSummaryBlock extends Block.Block { - overdue!: InfoCard.InfoCard; - toBePaid!: InfoCard.InfoCard; + overdue?: InfoCard.InfoCard; + toBePaid?: InfoCard.InfoCard; + layout?: 'vertical' | 'horizontal'; + chart?: PaymentsSummaryChart; } diff --git a/packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.orders-summary.mapper.ts b/packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.orders-summary.mapper.ts index 35ffa717c..7987c2476 100644 --- a/packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.orders-summary.mapper.ts +++ b/packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.orders-summary.mapper.ts @@ -113,7 +113,7 @@ const MOCK_ORDER_LIST_BLOCK_PL: CMS.Model.OrdersSummaryBlock.OrdersSummaryBlock icon: 'Package', }, chart: { - title: 'Liczba zamówień123', + title: 'Liczba zamówień', legend: { prev: 'Poprzedni okres', current: 'Obecny okres', diff --git a/packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.payments-summary.mapper.ts b/packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.payments-summary.mapper.ts index e05edd651..93b6ec967 100644 --- a/packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.payments-summary.mapper.ts +++ b/packages/integrations/mocked/src/modules/cms/mappers/blocks/cms.payments-summary.mapper.ts @@ -24,10 +24,20 @@ const MOCK_PAYMENTS_SUMMARY_BLOCK_EN: CMS.Model.PaymentsSummaryBlock.PaymentsSum }, icon: 'CreditCard', }, + chart: { + title: '6-months history', + topSegment: 'Overdue', + middleSegment: 'To be paid', + bottomSegment: 'Paid', + total: 'Total', + monthsToShow: 6, + showChart: true, + }, }; const MOCK_PAYMENTS_SUMMARY_BLOCK_PL: CMS.Model.PaymentsSummaryBlock.PaymentsSummaryBlock = { id: 'payments-summary-1', + layout: 'horizontal', overdue: { title: 'Zaległe', message: '{days} dni po terminie', @@ -54,6 +64,7 @@ const MOCK_PAYMENTS_SUMMARY_BLOCK_PL: CMS.Model.PaymentsSummaryBlock.PaymentsSum const MOCK_PAYMENTS_SUMMARY_BLOCK_DE: CMS.Model.PaymentsSummaryBlock.PaymentsSummaryBlock = { id: 'payments-summary-1', + layout: 'vertical', overdue: { title: 'Überfällig', message: '{days} Tage überfällig', diff --git a/packages/integrations/mocked/src/modules/cms/mappers/mocks/pages/invoice-list.page.ts b/packages/integrations/mocked/src/modules/cms/mappers/mocks/pages/invoice-list.page.ts index b5ac8b61e..50a607412 100644 --- a/packages/integrations/mocked/src/modules/cms/mappers/mocks/pages/invoice-list.page.ts +++ b/packages/integrations/mocked/src/modules/cms/mappers/mocks/pages/invoice-list.page.ts @@ -22,19 +22,14 @@ export const PAGE_INVOICE_LIST_EN: CMS.Model.Page.Page = { template: { __typename: 'TwoColumnTemplate', slots: { - top: [], - left: [ + top: [ { __typename: 'PaymentsSummaryBlock', id: 'payments-summary-1', }, ], - right: [ - { - __typename: 'PaymentsHistoryBlock', - id: 'payments-history-1', - }, - ], + left: [], + right: [], bottom: [ { __typename: 'InvoiceListBlock', @@ -73,19 +68,14 @@ export const PAGE_INVOICE_LIST_DE: CMS.Model.Page.Page = { template: { __typename: 'TwoColumnTemplate', slots: { - top: [], - left: [ + top: [ { __typename: 'PaymentsSummaryBlock', id: 'payments-summary-1', }, ], - right: [ - { - __typename: 'PaymentsHistoryBlock', - id: 'payments-history-1', - }, - ], + left: [], + right: [], bottom: [ { __typename: 'InvoiceListBlock', @@ -124,19 +114,14 @@ export const PAGE_INVOICE_LIST_PL: CMS.Model.Page.Page = { template: { __typename: 'TwoColumnTemplate', slots: { - top: [], - left: [ + top: [ { __typename: 'PaymentsSummaryBlock', id: 'payments-summary-1', }, ], - right: [ - { - __typename: 'PaymentsHistoryBlock', - id: 'payments-history-1', - }, - ], + left: [], + right: [], bottom: [ { __typename: 'InvoiceListBlock', diff --git a/packages/integrations/strapi-cms/generated/strapi.ts b/packages/integrations/strapi-cms/generated/strapi.ts index 8bd494b6e..e1c15a35e 100644 --- a/packages/integrations/strapi-cms/generated/strapi.ts +++ b/packages/integrations/strapi-cms/generated/strapi.ts @@ -11044,6 +11044,16 @@ export type GetComponentQuery = { page?: { slug: string; SEO: { title: string; description: string } }; }; }; + layout?: 'vertical' | 'horizontal'; + chart?: { + title?: string; + topSegment?: string; + middleSegment?: string; + bottomSegment?: string; + total?: string; + monthsToShow?: number; + showChart?: boolean; + }; } | { __typename: 'ComponentComponentsQuickLinks'; diff --git a/packages/integrations/strapi-cms/src/modules/cms/graphql/fragments/blocks/PaymentsSummary.graphql b/packages/integrations/strapi-cms/src/modules/cms/graphql/fragments/blocks/PaymentsSummary.graphql index 5f2f94429..dfba62022 100644 --- a/packages/integrations/strapi-cms/src/modules/cms/graphql/fragments/blocks/PaymentsSummary.graphql +++ b/packages/integrations/strapi-cms/src/modules/cms/graphql/fragments/blocks/PaymentsSummary.graphql @@ -1,10 +1,20 @@ fragment PaymentsSummaryComponent on ComponentComponentsPaymentsSummary { __typename id + layout overdue { ...InformationCard } toBePaid { ...InformationCard } + chart { + title + topSegment + middleSegment + bottomSegment + total + showChart + monthsToShow + } } diff --git a/packages/integrations/strapi-cms/src/modules/cms/mappers/blocks/cms.payments-summary.mapper.ts b/packages/integrations/strapi-cms/src/modules/cms/mappers/blocks/cms.payments-summary.mapper.ts index f940107ce..913589de9 100644 --- a/packages/integrations/strapi-cms/src/modules/cms/mappers/blocks/cms.payments-summary.mapper.ts +++ b/packages/integrations/strapi-cms/src/modules/cms/mappers/blocks/cms.payments-summary.mapper.ts @@ -19,8 +19,20 @@ export const mapPaymentsSummaryBlock = ( case 'ComponentComponentsPaymentsSummary': return { id: component.id, + layout: component.layout || undefined, toBePaid: mapInfoCard(component.toBePaid), overdue: mapInfoCard(component.overdue), + chart: component.chart + ? { + title: component.chart.title!, + topSegment: component.chart.topSegment!, + middleSegment: component.chart.middleSegment!, + bottomSegment: component.chart.bottomSegment!, + total: component.chart.total!, + showChart: component.chart.showChart!, + monthsToShow: component.chart.monthsToShow!, + } + : undefined, }; } From 95321a8b5e57d5d6ad34a726a8da7080579d0c96 Mon Sep 17 00:00:00 2001 From: Michal Nowak Date: Thu, 13 Nov 2025 17:54:30 +0100 Subject: [PATCH 3/6] refactor(ui): reverted strapi integrations --- packages/integrations/strapi-cms/generated/strapi.ts | 10 ---------- .../graphql/fragments/blocks/PaymentsSummary.graphql | 10 ---------- .../mappers/blocks/cms.payments-summary.mapper.ts | 12 ------------ 3 files changed, 32 deletions(-) diff --git a/packages/integrations/strapi-cms/generated/strapi.ts b/packages/integrations/strapi-cms/generated/strapi.ts index e1c15a35e..8bd494b6e 100644 --- a/packages/integrations/strapi-cms/generated/strapi.ts +++ b/packages/integrations/strapi-cms/generated/strapi.ts @@ -11044,16 +11044,6 @@ export type GetComponentQuery = { page?: { slug: string; SEO: { title: string; description: string } }; }; }; - layout?: 'vertical' | 'horizontal'; - chart?: { - title?: string; - topSegment?: string; - middleSegment?: string; - bottomSegment?: string; - total?: string; - monthsToShow?: number; - showChart?: boolean; - }; } | { __typename: 'ComponentComponentsQuickLinks'; diff --git a/packages/integrations/strapi-cms/src/modules/cms/graphql/fragments/blocks/PaymentsSummary.graphql b/packages/integrations/strapi-cms/src/modules/cms/graphql/fragments/blocks/PaymentsSummary.graphql index dfba62022..5f2f94429 100644 --- a/packages/integrations/strapi-cms/src/modules/cms/graphql/fragments/blocks/PaymentsSummary.graphql +++ b/packages/integrations/strapi-cms/src/modules/cms/graphql/fragments/blocks/PaymentsSummary.graphql @@ -1,20 +1,10 @@ fragment PaymentsSummaryComponent on ComponentComponentsPaymentsSummary { __typename id - layout overdue { ...InformationCard } toBePaid { ...InformationCard } - chart { - title - topSegment - middleSegment - bottomSegment - total - showChart - monthsToShow - } } diff --git a/packages/integrations/strapi-cms/src/modules/cms/mappers/blocks/cms.payments-summary.mapper.ts b/packages/integrations/strapi-cms/src/modules/cms/mappers/blocks/cms.payments-summary.mapper.ts index 913589de9..f940107ce 100644 --- a/packages/integrations/strapi-cms/src/modules/cms/mappers/blocks/cms.payments-summary.mapper.ts +++ b/packages/integrations/strapi-cms/src/modules/cms/mappers/blocks/cms.payments-summary.mapper.ts @@ -19,20 +19,8 @@ export const mapPaymentsSummaryBlock = ( case 'ComponentComponentsPaymentsSummary': return { id: component.id, - layout: component.layout || undefined, toBePaid: mapInfoCard(component.toBePaid), overdue: mapInfoCard(component.overdue), - chart: component.chart - ? { - title: component.chart.title!, - topSegment: component.chart.topSegment!, - middleSegment: component.chart.middleSegment!, - bottomSegment: component.chart.bottomSegment!, - total: component.chart.total!, - showChart: component.chart.showChart!, - monthsToShow: component.chart.monthsToShow!, - } - : undefined, }; } From 0f389f78e302b61d62ad4885f90fbd43010e7b86 Mon Sep 17 00:00:00 2001 From: Michal Nowak Date: Thu, 13 Nov 2025 18:00:37 +0100 Subject: [PATCH 4/6] refactor(ui): reverted strapi implementation --- .../cms/mappers/blocks/cms.orders-summary.mapper.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/packages/integrations/strapi-cms/src/modules/cms/mappers/blocks/cms.orders-summary.mapper.ts b/packages/integrations/strapi-cms/src/modules/cms/mappers/blocks/cms.orders-summary.mapper.ts index 19c6f0e34..f13d90771 100644 --- a/packages/integrations/strapi-cms/src/modules/cms/mappers/blocks/cms.orders-summary.mapper.ts +++ b/packages/integrations/strapi-cms/src/modules/cms/mappers/blocks/cms.orders-summary.mapper.ts @@ -29,13 +29,14 @@ export const mapOrdersSummaryBlock = (data: GetComponentQuery): CMS.Model.Orders title: component.averageNumber.title, icon: component.averageNumber.icon, }, + // TODO: These values are hardcoded and require implementation to fetch real data. chart: { - title: component.chartTitle, + title: 'Number of orders', legend: { - prev: component.chartPreviousPeriodLabel, - current: component.chartCurrentPeriodLabel, + prev: 'Previous period', + current: 'Current period', }, - showChart: component.showChart, + showChart: true, }, ranges: component.ranges?.map((range) => ({ label: range.label, From c7476eb19b42c796930fc34b83e3ddab4c45a911 Mon Sep 17 00:00:00 2001 From: Michal Nowak Date: Fri, 14 Nov 2025 10:39:51 +0100 Subject: [PATCH 5/6] feat(ui): add layout option to Orders Summary block --- .../src/api-harmonization/orders-summary.mapper.ts | 1 + .../src/api-harmonization/orders-summary.model.ts | 1 + .../orders-summary/src/frontend/OrdersSummary.client.tsx | 6 ++++-- .../src/modules/cms/models/blocks/orders-summary.model.ts | 1 + .../modules/cms/mappers/blocks/cms.orders-summary.mapper.ts | 1 + 5 files changed, 8 insertions(+), 2 deletions(-) diff --git a/packages/blocks/orders-summary/src/api-harmonization/orders-summary.mapper.ts b/packages/blocks/orders-summary/src/api-harmonization/orders-summary.mapper.ts index 9275a7165..a9b80b91f 100644 --- a/packages/blocks/orders-summary/src/api-harmonization/orders-summary.mapper.ts +++ b/packages/blocks/orders-summary/src/api-harmonization/orders-summary.mapper.ts @@ -65,6 +65,7 @@ export const mapOrdersSummary = ( }, noResults: cms.noResults, ranges: cms.ranges, + layout: cms.layout, }; }; diff --git a/packages/blocks/orders-summary/src/api-harmonization/orders-summary.model.ts b/packages/blocks/orders-summary/src/api-harmonization/orders-summary.model.ts index ec342f669..2c158cb4e 100644 --- a/packages/blocks/orders-summary/src/api-harmonization/orders-summary.model.ts +++ b/packages/blocks/orders-summary/src/api-harmonization/orders-summary.model.ts @@ -36,6 +36,7 @@ export class OrdersSummaryBlock extends ApiModels.Block.Block { showChart?: boolean; }; ranges!: CMS.Model.OrdersSummaryBlock.OrdersSummaryBlock['ranges']; + layout?: 'vertical' | 'horizontal'; noResults!: CMS.Model.OrdersSummaryBlock.OrdersSummaryBlock['noResults']; } diff --git a/packages/blocks/orders-summary/src/frontend/OrdersSummary.client.tsx b/packages/blocks/orders-summary/src/frontend/OrdersSummary.client.tsx index ff0d121d0..0e9f44f42 100644 --- a/packages/blocks/orders-summary/src/frontend/OrdersSummary.client.tsx +++ b/packages/blocks/orders-summary/src/frontend/OrdersSummary.client.tsx @@ -66,6 +66,8 @@ export const OrdersSummaryPure: React.FC> = ({ const [isPending, startTransition] = useTransition(); + const cardsLayout = component.layout === 'horizontal' ? 'flex-col md:flex-row' : 'flex-col'; + const handleFilter = (value: string) => { startTransition(async () => { let dateFrom: string; @@ -130,7 +132,7 @@ export const OrdersSummaryPure: React.FC> = ({ > {data.chart.showChart ? ( <> -
+
> = ({ ) : ( -
+
Date: Fri, 14 Nov 2025 11:29:52 +0100 Subject: [PATCH 6/6] fix(ui): update order details mapping to handle optional CMS fields --- .../api-harmonization/order-details.mapper.ts | 40 +++++++++---------- .../cms/models/blocks/order-details.model.ts | 12 +++--- .../mappers/cms.information-card.mapper.ts | 8 +++- 3 files changed, 33 insertions(+), 27 deletions(-) diff --git a/packages/blocks/order-details/src/api-harmonization/order-details.mapper.ts b/packages/blocks/order-details/src/api-harmonization/order-details.mapper.ts index a967f359e..afdc79b00 100644 --- a/packages/blocks/order-details/src/api-harmonization/order-details.mapper.ts +++ b/packages/blocks/order-details/src/api-harmonization/order-details.mapper.ts @@ -33,16 +33,16 @@ export const mapOrderDetails = ( value: order.id, }, subtotal: { - title: cms.totalValue.title, - icon: cms.totalValue.icon, + title: cms.totalValue?.title || '', + icon: cms.totalValue?.icon, label: Utils.Price.checkNegativeValue(order.subtotal || { value: 0, currency }).value.toString(), - description: format(cms.totalValue.message || '', { + description: format(cms.totalValue?.message || '', { value: order.items.total, }), value: order.subtotal, }, createdAt: { - title: cms.createdOrderAt.title, + title: cms.createdOrderAt?.title || '', label: Utils.Date.formatDateRelative( order.createdAt, locale, @@ -50,12 +50,12 @@ export const mapOrderDetails = ( cms.labels.yesterday, timezone, ), - icon: cms.createdOrderAt.icon, + icon: cms.createdOrderAt?.icon, description: Utils.Date.formatTime(order.createdAt, locale, timezone), value: order.createdAt, }, paymentDueDate: { - title: cms.paymentDueDate.title, + title: cms.paymentDueDate?.title || '', label: order.paymentDueDate ? Utils.Date.formatDateRelative( order.paymentDueDate, @@ -65,41 +65,41 @@ export const mapOrderDetails = ( timezone, ) : '-', - icon: cms.paymentDueDate.icon, + icon: cms.paymentDueDate?.icon, description: order.documents?.[0]?.id - ? format(cms.paymentDueDate.message || '', { + ? format(cms.paymentDueDate?.message || '', { value: order.documents?.[0]?.id, }) - : cms.paymentDueDate.altMessage, + : cms.paymentDueDate?.altMessage, value: order.paymentDueDate, }, overdue: { - title: cms.overdue.title, - icon: cms.overdue.icon, + title: cms.overdue?.title || '', + icon: cms.overdue?.icon, label: Utils.Price.checkNegativeValue({ value: overdueAmount, currency }).value.toString(), description: isOverdue - ? format(cms.overdue.message || '', { + ? format(cms.overdue?.message || '', { days: overdueDays, }) - : cms.overdue.altMessage, + : cms.overdue?.altMessage, value: { value: Utils.Price.checkNegativeValue({ value: overdueAmount, currency }).value, currency }, isOverdue, }, status: { - title: cms.orderStatus.title, - icon: cms.orderStatus.icon, + title: cms.orderStatus?.title || '', + icon: cms.orderStatus?.icon, label: cms.fieldMapping.status?.[order.status] || order.status, value: order.status, statusLadder: cms.statusLadder, }, customerComment: { - title: cms.customerComment.title, - icon: cms.customerComment.icon, + title: cms.customerComment?.title || '', + icon: cms.customerComment?.icon, value: order.customerComment, link: { - label: cms.customerComment.link?.label, - icon: cms.customerComment.link?.icon, - url: cms.customerComment.link?.url, + label: cms.customerComment?.link?.label, + icon: cms.customerComment?.link?.icon, + url: cms.customerComment?.link?.url, }, }, }, diff --git a/packages/framework/src/modules/cms/models/blocks/order-details.model.ts b/packages/framework/src/modules/cms/models/blocks/order-details.model.ts index 9892da32a..f80b1f489 100644 --- a/packages/framework/src/modules/cms/models/blocks/order-details.model.ts +++ b/packages/framework/src/modules/cms/models/blocks/order-details.model.ts @@ -22,12 +22,12 @@ export class OrderDetailsBlock extends Block.Block { showMore: string; close: string; }; - totalValue!: InfoCard.InfoCard; - createdOrderAt!: InfoCard.InfoCard; - paymentDueDate!: InfoCard.InfoCard; - overdue!: InfoCard.InfoCard; - orderStatus!: InfoCard.InfoCard; - customerComment!: InfoCard.InfoCard; + totalValue?: InfoCard.InfoCard; + createdOrderAt?: InfoCard.InfoCard; + paymentDueDate?: InfoCard.InfoCard; + overdue?: InfoCard.InfoCard; + orderStatus?: InfoCard.InfoCard; + customerComment?: InfoCard.InfoCard; reorderLabel?: string; trackOrderLabel?: string; payOnlineLabel?: string; diff --git a/packages/integrations/strapi-cms/src/modules/cms/mappers/cms.information-card.mapper.ts b/packages/integrations/strapi-cms/src/modules/cms/mappers/cms.information-card.mapper.ts index f8fa2f476..f8eeaece9 100644 --- a/packages/integrations/strapi-cms/src/modules/cms/mappers/cms.information-card.mapper.ts +++ b/packages/integrations/strapi-cms/src/modules/cms/mappers/cms.information-card.mapper.ts @@ -2,7 +2,13 @@ import { Models } from '@o2s/framework/modules'; import { InformationCardFragment } from '@/generated/strapi'; -export const mapInfoCard = (component: InformationCardFragment): Models.InfoCard.InfoCard => { +export const mapInfoCard = ( + component: InformationCardFragment | null | undefined, +): Models.InfoCard.InfoCard | undefined => { + if (!component) { + return undefined; + } + return { title: component.title, icon: component.icon,