Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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'];
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,7 @@ export const Default: Story = {
prev: 'Previous period',
current: 'Current period',
},
showChart: true,
},
noResults: {
title: "So far, there's nothing here",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -125,20 +125,70 @@ export const OrdersSummaryPure: React.FC<Readonly<OrdersSummaryPureProps>> = ({
)}
</div>

<div className="w-full flex flex-col lg:flex-row gap-6">
<div className="w-full flex flex-col gap-6">
<InfoCard
title={data.totalValue.title}
value={
<Typography variant="highlightedBig">
<Price price={data.totalValue.value} />
</Typography>
}
description={<Trend value={data.totalValue.trend} />}
icon={data.totalValue.icon}
/>

<div className="w-full flex flex-col sm:flex-row gap-6">
<div
className={cn('w-full flex gap-6', data.chart.showChart ? 'flex-col lg:flex-row' : 'flex-col')}
>
{data.chart.showChart ? (
<>
<div className="w-full flex flex-col gap-6">
<InfoCard
title={data.totalValue.title}
value={
<Typography variant="highlightedBig">
<Price price={data.totalValue.value} />
</Typography>
}
description={<Trend value={data.totalValue.trend} />}
icon={data.totalValue.icon}
/>

<div className="w-full flex flex-col sm:flex-row gap-6">
<InfoCard
title={data.averageValue.title}
value={
<Typography variant="highlightedBig">
<Price price={data.averageValue.value} />
</Typography>
}
description={<Trend value={data.averageValue.trend} />}
icon={data.averageValue.icon}
/>
<InfoCard
title={data.averageNumber.title}
value={
<Typography variant="highlightedBig">
{data.averageNumber.value}
</Typography>
}
description={<Trend value={data.averageNumber.trend} />}
icon={data.averageNumber.icon}
/>
</div>
</div>
<Card className="h-full w-full">
<div className="p-6 flex flex-col gap-6">
<Typography variant="subtitle">{data.chart.title}</Typography>

<DoubleLineChart
chartData={data.chart.data}
legend={data.chart.legend}
tooltipType="number"
/>
</div>
</Card>
</>
) : (
<div className="w-full flex flex-col md:flex-row gap-6">
<InfoCard
title={data.totalValue.title}
value={
<Typography variant="highlightedBig">
<Price price={data.totalValue.value} />
</Typography>
}
description={<Trend value={data.totalValue.trend} />}
icon={data.totalValue.icon}
/>
<InfoCard
title={data.averageValue.title}
value={
Expand All @@ -156,19 +206,7 @@ export const OrdersSummaryPure: React.FC<Readonly<OrdersSummaryPureProps>> = ({
icon={data.averageNumber.icon}
/>
</div>
</div>

<Card className="h-full w-full">
<div className="p-6 flex flex-col gap-6">
<Typography variant="subtitle">{data.chart.title}</Typography>

<DoubleLineChart
chartData={data.chart.data}
legend={data.chart.legend}
tooltipType="number"
/>
</div>
</Card>
)}
</div>
</div>
</LoadingOverlay>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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
Expand All @@ -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),
}));
};
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -17,7 +17,7 @@ export class PaymentsSummaryBlock extends ApiModels.Block.Block {
};
isOverdue: boolean;
};
toBePaid!: {
toBePaid?: {
title: string;
icon?: string;
value: Models.Price.Price;
Expand All @@ -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;
}
Loading