@cloud-ru/uikit-product-price-summary 2.0.5 → 2.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +12 -0
- package/dist/cjs/components/PriceSummary/components/CoveredByGrantLabel/CoveredByGrantLabel.d.ts +5 -0
- package/dist/cjs/components/PriceSummary/components/CoveredByGrantLabel/CoveredByGrantLabel.js +16 -0
- package/dist/cjs/components/PriceSummary/components/CoveredByGrantLabel/index.d.ts +1 -0
- package/dist/cjs/components/PriceSummary/components/CoveredByGrantLabel/index.js +17 -0
- package/dist/cjs/components/PriceSummary/components/CoveredByGrantLabel/styles.module.css +6 -0
- package/dist/cjs/components/PriceSummary/components/InvoiceDetailsBlock/InvoiceDetailsBlock.js +8 -1
- package/dist/cjs/components/PriceSummary/components/InvoiceItemBlock/InvoiceItemBlock.d.ts +2 -1
- package/dist/cjs/components/PriceSummary/components/InvoiceItemBlock/InvoiceItemBlock.js +3 -2
- package/dist/cjs/types/index.d.ts +10 -2
- package/dist/esm/components/PriceSummary/components/CoveredByGrantLabel/CoveredByGrantLabel.d.ts +5 -0
- package/dist/esm/components/PriceSummary/components/CoveredByGrantLabel/CoveredByGrantLabel.js +10 -0
- package/dist/esm/components/PriceSummary/components/CoveredByGrantLabel/index.d.ts +1 -0
- package/dist/esm/components/PriceSummary/components/CoveredByGrantLabel/index.js +1 -0
- package/dist/esm/components/PriceSummary/components/CoveredByGrantLabel/styles.module.css +6 -0
- package/dist/esm/components/PriceSummary/components/InvoiceDetailsBlock/InvoiceDetailsBlock.js +8 -1
- package/dist/esm/components/PriceSummary/components/InvoiceItemBlock/InvoiceItemBlock.d.ts +2 -1
- package/dist/esm/components/PriceSummary/components/InvoiceItemBlock/InvoiceItemBlock.js +3 -2
- package/dist/esm/types/index.d.ts +10 -2
- package/package.json +2 -2
- package/src/components/PriceSummary/components/CoveredByGrantLabel/CoveredByGrantLabel.tsx +32 -0
- package/src/components/PriceSummary/components/CoveredByGrantLabel/index.ts +1 -0
- package/src/components/PriceSummary/components/CoveredByGrantLabel/styles.module.scss +8 -0
- package/src/components/PriceSummary/components/InvoiceDetailsBlock/InvoiceDetailsBlock.tsx +17 -1
- package/src/components/PriceSummary/components/InvoiceDetailsBlock/styles.module.scss +1 -1
- package/src/components/PriceSummary/components/InvoiceItemBlock/InvoiceItemBlock.tsx +6 -1
- package/src/types/index.ts +13 -2
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
3
3
|
All notable changes to this project will be documented in this file.
|
|
4
4
|
See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
|
|
5
5
|
|
|
6
|
+
# 2.1.0 (2026-02-17)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* **PDS-3467:** add coveredByGrant to PriceSummary ([db3491f](https://github.com/cloud-ru-tech/uikit-product/commit/db3491f9e44be375ec8c8191e0ebed9f45d546db))
|
|
12
|
+
* **PDS-3467:** add coveredByGrant to PriceSummary ([11bd338](https://github.com/cloud-ru-tech/uikit-product/commit/11bd338b9b77e0fec883770c6f10d957203bd4d0))
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
|
|
6
18
|
## 2.0.5 (2026-02-16)
|
|
7
19
|
|
|
8
20
|
|
package/dist/cjs/components/PriceSummary/components/CoveredByGrantLabel/CoveredByGrantLabel.js
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
3
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
4
|
+
};
|
|
5
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
6
|
+
exports.CoveredByGrantLabel = CoveredByGrantLabel;
|
|
7
|
+
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
|
+
const classnames_1 = __importDefault(require("classnames"));
|
|
9
|
+
const uikit_product_locale_1 = require("@cloud-ru/uikit-product-locale");
|
|
10
|
+
const promo_tag_1 = require("@snack-uikit/promo-tag");
|
|
11
|
+
const tooltip_1 = require("@snack-uikit/tooltip");
|
|
12
|
+
const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
|
|
13
|
+
function CoveredByGrantLabel({ covered, className }) {
|
|
14
|
+
const { t } = (0, uikit_product_locale_1.useLocale)('PriceSummary');
|
|
15
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: (0, classnames_1.default)(styles_module_scss_1.default.coveredByGrant, className), children: [(0, jsx_runtime_1.jsx)(promo_tag_1.PromoTag, { appearance: covered ? 'green' : 'neutral', color: 'decor', text: covered ? t('coveredByGrant') : t('notCoveredByGrant') }), (0, jsx_runtime_1.jsx)(tooltip_1.QuestionTooltip, { tip: covered ? t('coveredByGrantTooltip') : t('notCoveredByGrantTooltip'), size: 'xs', placement: 'top', trigger: 'hover', tabIndex: -1 })] }));
|
|
16
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './CoveredByGrantLabel';
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
|
|
3
|
+
if (k2 === undefined) k2 = k;
|
|
4
|
+
var desc = Object.getOwnPropertyDescriptor(m, k);
|
|
5
|
+
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
|
|
6
|
+
desc = { enumerable: true, get: function() { return m[k]; } };
|
|
7
|
+
}
|
|
8
|
+
Object.defineProperty(o, k2, desc);
|
|
9
|
+
}) : (function(o, m, k, k2) {
|
|
10
|
+
if (k2 === undefined) k2 = k;
|
|
11
|
+
o[k2] = m[k];
|
|
12
|
+
}));
|
|
13
|
+
var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
14
|
+
for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
|
|
15
|
+
};
|
|
16
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
|
+
__exportStar(require("./CoveredByGrantLabel"), exports);
|
package/dist/cjs/components/PriceSummary/components/InvoiceDetailsBlock/InvoiceDetailsBlock.js
CHANGED
|
@@ -8,10 +8,17 @@ const jsx_runtime_1 = require("react/jsx-runtime");
|
|
|
8
8
|
const uikit_product_locale_1 = require("@cloud-ru/uikit-product-locale");
|
|
9
9
|
const typography_1 = require("@snack-uikit/typography");
|
|
10
10
|
const helpers_1 = require("../../../../helpers");
|
|
11
|
+
const CoveredByGrantLabel_1 = require("../CoveredByGrantLabel");
|
|
11
12
|
const Divider_1 = require("../Divider");
|
|
12
13
|
const InvoiceItemBlock_1 = require("../InvoiceItemBlock");
|
|
13
14
|
const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
|
|
14
15
|
function InvoiceDetailsBlock({ invoice, layoutType }) {
|
|
16
|
+
var _a;
|
|
15
17
|
const { t } = (0, uikit_product_locale_1.useLocale)('PriceSummary');
|
|
16
|
-
|
|
18
|
+
const primaryItems = invoice.items.filter(item => item.primary);
|
|
19
|
+
const firstValue = (_a = primaryItems[0]) === null || _a === void 0 ? void 0 : _a.coveredByGrant;
|
|
20
|
+
const allSameValue = primaryItems.length > 0 && primaryItems.every(item => item.coveredByGrant === firstValue);
|
|
21
|
+
const showBlockLabel = allSameValue && firstValue !== undefined;
|
|
22
|
+
const showItemLabels = !showBlockLabel;
|
|
23
|
+
return ((0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.main, children: [showBlockLabel && (0, jsx_runtime_1.jsx)(CoveredByGrantLabel_1.CoveredByGrantLabel, { covered: firstValue }), invoice.title && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.header, children: [(0, jsx_runtime_1.jsx)(typography_1.Typography.SansLabelM, { children: invoice.title }), invoice.quantity && (0, jsx_runtime_1.jsx)(typography_1.Typography.SansLabelM, { children: (0, helpers_1.formatQuantity)(invoice.quantity) })] }), (0, jsx_runtime_1.jsx)(Divider_1.Divider, {})] })), invoice.items.map((item, index) => ((0, jsx_runtime_1.jsx)(InvoiceItemBlock_1.InvoiceItemBlock, { item: item, index: index, layoutType: layoutType, showCoveredByGrantLabel: showItemLabels }, index))), invoice.price !== undefined && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)(Divider_1.Divider, {}), (0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.footer, children: (0, jsx_runtime_1.jsxs)(typography_1.Typography.SansLabelM, { children: [t('price'), ": ", (0, helpers_1.formatCurrency)(invoice.price)] }) })] }))] }));
|
|
17
24
|
}
|
|
@@ -3,5 +3,6 @@ import { InvoiceItem } from '../../../../types';
|
|
|
3
3
|
export type InvoiceItemBlockProps = WithLayoutType<{
|
|
4
4
|
item: InvoiceItem;
|
|
5
5
|
index: number;
|
|
6
|
+
showCoveredByGrantLabel?: boolean;
|
|
6
7
|
}>;
|
|
7
|
-
export declare function InvoiceItemBlock({ item, index, layoutType }: InvoiceItemBlockProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export declare function InvoiceItemBlock({ item, index, layoutType, showCoveredByGrantLabel }: InvoiceItemBlockProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -7,11 +7,12 @@ exports.InvoiceItemBlock = InvoiceItemBlock;
|
|
|
7
7
|
const jsx_runtime_1 = require("react/jsx-runtime");
|
|
8
8
|
const typography_1 = require("@snack-uikit/typography");
|
|
9
9
|
const helpers_1 = require("../../../../helpers");
|
|
10
|
+
const CoveredByGrantLabel_1 = require("../CoveredByGrantLabel");
|
|
10
11
|
const DiscountPercentCell_1 = require("../DiscountPercentCell");
|
|
11
12
|
const Divider_1 = require("../Divider");
|
|
12
13
|
const InvoiceItemLabelCell_1 = require("../InvoiceItemLabelCell");
|
|
13
14
|
const styles_module_scss_1 = __importDefault(require('./styles.module.css'));
|
|
14
|
-
function InvoiceItemBlock({ item, index, layoutType }) {
|
|
15
|
+
function InvoiceItemBlock({ item, index, layoutType, showCoveredByGrantLabel }) {
|
|
15
16
|
const isEven = (index + 1) % 2 === 0;
|
|
16
17
|
const isSecondary = item.primary === undefined ? isEven : !item.primary;
|
|
17
18
|
const getPriceItem = () => {
|
|
@@ -20,5 +21,5 @@ function InvoiceItemBlock({ item, index, layoutType }) {
|
|
|
20
21
|
}
|
|
21
22
|
return item.price !== undefined ? (0, helpers_1.formatCurrency)(item.price) : undefined;
|
|
22
23
|
};
|
|
23
|
-
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [item.topDivider && (0, jsx_runtime_1.jsx)(Divider_1.Divider, {}), (0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.itemGrid, "data-discount": Boolean(item.discount), children: ['label' in item && item.label !== undefined && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.labelCell, "data-secondary": isSecondary, children: (0, jsx_runtime_1.jsx)(InvoiceItemLabelCell_1.InvoiceItemLabelCell, { item: item, layoutType: layoutType }) }), (0, jsx_runtime_1.jsx)(typography_1.Typography.SansBodyS, { tag: 'div', className: styles_module_scss_1.default.priceCell, "data-secondary": isSecondary, children: getPriceItem() })] })), item.discount && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.percentCell, "data-secondary": isSecondary, children: (0, jsx_runtime_1.jsx)(DiscountPercentCell_1.DiscountPercentCell, { discount: item.discount, layoutType: layoutType }) }), (0, jsx_runtime_1.jsx)(typography_1.Typography.SansBodyS, { tag: 'div', className: styles_module_scss_1.default.discountCell, "data-secondary": isSecondary, children: (0, helpers_1.formatCurrency)(-Math.abs(item.discount.value)) })] }))] }), item.bottomDivider && (0, jsx_runtime_1.jsx)(Divider_1.Divider, {})] }));
|
|
24
|
+
return ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [item.topDivider && (0, jsx_runtime_1.jsx)(Divider_1.Divider, {}), item.coveredByGrant !== undefined && showCoveredByGrantLabel && ((0, jsx_runtime_1.jsx)(CoveredByGrantLabel_1.CoveredByGrantLabel, { covered: item.coveredByGrant })), (0, jsx_runtime_1.jsxs)("div", { className: styles_module_scss_1.default.itemGrid, "data-discount": Boolean(item.discount), children: ['label' in item && item.label !== undefined && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.labelCell, "data-secondary": isSecondary, children: (0, jsx_runtime_1.jsx)(InvoiceItemLabelCell_1.InvoiceItemLabelCell, { item: item, layoutType: layoutType }) }), (0, jsx_runtime_1.jsx)(typography_1.Typography.SansBodyS, { tag: 'div', className: styles_module_scss_1.default.priceCell, "data-secondary": isSecondary, children: getPriceItem() })] })), item.discount && ((0, jsx_runtime_1.jsxs)(jsx_runtime_1.Fragment, { children: [(0, jsx_runtime_1.jsx)("div", { className: styles_module_scss_1.default.percentCell, "data-secondary": isSecondary, children: (0, jsx_runtime_1.jsx)(DiscountPercentCell_1.DiscountPercentCell, { discount: item.discount, layoutType: layoutType }) }), (0, jsx_runtime_1.jsx)(typography_1.Typography.SansBodyS, { tag: 'div', className: styles_module_scss_1.default.discountCell, "data-secondary": isSecondary, children: (0, helpers_1.formatCurrency)(-Math.abs(item.discount.value)) })] }))] }), item.bottomDivider && (0, jsx_runtime_1.jsx)(Divider_1.Divider, {})] }));
|
|
24
25
|
}
|
|
@@ -23,16 +23,24 @@ export type PriceInvoiceItem = {
|
|
|
23
23
|
export type DiscountInvoiceItem = {
|
|
24
24
|
discount: DiscountItem;
|
|
25
25
|
};
|
|
26
|
-
export type
|
|
26
|
+
export type BaseInvoiceItem = (PriceInvoiceItem | DiscountInvoiceItem) & {
|
|
27
27
|
labelTooltip?: QuestionTooltipProps['tip'];
|
|
28
28
|
price?: number;
|
|
29
29
|
hidePrice?: boolean;
|
|
30
30
|
labelMaxLines?: number;
|
|
31
31
|
quantity?: string | number;
|
|
32
|
-
primary?: boolean;
|
|
33
32
|
topDivider?: boolean;
|
|
34
33
|
bottomDivider?: boolean;
|
|
35
34
|
};
|
|
35
|
+
export type PrimaryInvoiceItem = BaseInvoiceItem & {
|
|
36
|
+
primary: true;
|
|
37
|
+
coveredByGrant?: boolean;
|
|
38
|
+
};
|
|
39
|
+
export type SecondaryInvoiceItem = BaseInvoiceItem & {
|
|
40
|
+
primary?: false;
|
|
41
|
+
coveredByGrant?: never;
|
|
42
|
+
};
|
|
43
|
+
export type InvoiceItem = PrimaryInvoiceItem | SecondaryInvoiceItem;
|
|
36
44
|
export type InvoiceDetails = {
|
|
37
45
|
title?: string;
|
|
38
46
|
quantity?: string | number;
|
package/dist/esm/components/PriceSummary/components/CoveredByGrantLabel/CoveredByGrantLabel.js
ADDED
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import cn from 'classnames';
|
|
3
|
+
import { useLocale } from '@cloud-ru/uikit-product-locale';
|
|
4
|
+
import { PromoTag } from '@snack-uikit/promo-tag';
|
|
5
|
+
import { QuestionTooltip } from '@snack-uikit/tooltip';
|
|
6
|
+
import styles from './styles.module.css';
|
|
7
|
+
export function CoveredByGrantLabel({ covered, className }) {
|
|
8
|
+
const { t } = useLocale('PriceSummary');
|
|
9
|
+
return (_jsxs("div", { className: cn(styles.coveredByGrant, className), children: [_jsx(PromoTag, { appearance: covered ? 'green' : 'neutral', color: 'decor', text: covered ? t('coveredByGrant') : t('notCoveredByGrant') }), _jsx(QuestionTooltip, { tip: covered ? t('coveredByGrantTooltip') : t('notCoveredByGrantTooltip'), size: 'xs', placement: 'top', trigger: 'hover', tabIndex: -1 })] }));
|
|
10
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './CoveredByGrantLabel';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './CoveredByGrantLabel';
|
package/dist/esm/components/PriceSummary/components/InvoiceDetailsBlock/InvoiceDetailsBlock.js
CHANGED
|
@@ -2,10 +2,17 @@ import { jsx as _jsx, jsxs as _jsxs, Fragment as _Fragment } from "react/jsx-run
|
|
|
2
2
|
import { useLocale } from '@cloud-ru/uikit-product-locale';
|
|
3
3
|
import { Typography } from '@snack-uikit/typography';
|
|
4
4
|
import { formatCurrency, formatQuantity } from '../../../../helpers';
|
|
5
|
+
import { CoveredByGrantLabel } from '../CoveredByGrantLabel';
|
|
5
6
|
import { Divider } from '../Divider';
|
|
6
7
|
import { InvoiceItemBlock } from '../InvoiceItemBlock';
|
|
7
8
|
import styles from './styles.module.css';
|
|
8
9
|
export function InvoiceDetailsBlock({ invoice, layoutType }) {
|
|
10
|
+
var _a;
|
|
9
11
|
const { t } = useLocale('PriceSummary');
|
|
10
|
-
|
|
12
|
+
const primaryItems = invoice.items.filter(item => item.primary);
|
|
13
|
+
const firstValue = (_a = primaryItems[0]) === null || _a === void 0 ? void 0 : _a.coveredByGrant;
|
|
14
|
+
const allSameValue = primaryItems.length > 0 && primaryItems.every(item => item.coveredByGrant === firstValue);
|
|
15
|
+
const showBlockLabel = allSameValue && firstValue !== undefined;
|
|
16
|
+
const showItemLabels = !showBlockLabel;
|
|
17
|
+
return (_jsxs("div", { className: styles.main, children: [showBlockLabel && _jsx(CoveredByGrantLabel, { covered: firstValue }), invoice.title && (_jsxs(_Fragment, { children: [_jsxs("div", { className: styles.header, children: [_jsx(Typography.SansLabelM, { children: invoice.title }), invoice.quantity && _jsx(Typography.SansLabelM, { children: formatQuantity(invoice.quantity) })] }), _jsx(Divider, {})] })), invoice.items.map((item, index) => (_jsx(InvoiceItemBlock, { item: item, index: index, layoutType: layoutType, showCoveredByGrantLabel: showItemLabels }, index))), invoice.price !== undefined && (_jsxs(_Fragment, { children: [_jsx(Divider, {}), _jsx("div", { className: styles.footer, children: _jsxs(Typography.SansLabelM, { children: [t('price'), ": ", formatCurrency(invoice.price)] }) })] }))] }));
|
|
11
18
|
}
|
|
@@ -3,5 +3,6 @@ import { InvoiceItem } from '../../../../types';
|
|
|
3
3
|
export type InvoiceItemBlockProps = WithLayoutType<{
|
|
4
4
|
item: InvoiceItem;
|
|
5
5
|
index: number;
|
|
6
|
+
showCoveredByGrantLabel?: boolean;
|
|
6
7
|
}>;
|
|
7
|
-
export declare function InvoiceItemBlock({ item, index, layoutType }: InvoiceItemBlockProps): import("react/jsx-runtime").JSX.Element;
|
|
8
|
+
export declare function InvoiceItemBlock({ item, index, layoutType, showCoveredByGrantLabel }: InvoiceItemBlockProps): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
2
|
import { Typography } from '@snack-uikit/typography';
|
|
3
3
|
import { formatCurrency } from '../../../../helpers';
|
|
4
|
+
import { CoveredByGrantLabel } from '../CoveredByGrantLabel';
|
|
4
5
|
import { DiscountPercentCell } from '../DiscountPercentCell';
|
|
5
6
|
import { Divider } from '../Divider';
|
|
6
7
|
import { InvoiceItemLabelCell } from '../InvoiceItemLabelCell';
|
|
7
8
|
import styles from './styles.module.css';
|
|
8
|
-
export function InvoiceItemBlock({ item, index, layoutType }) {
|
|
9
|
+
export function InvoiceItemBlock({ item, index, layoutType, showCoveredByGrantLabel }) {
|
|
9
10
|
const isEven = (index + 1) % 2 === 0;
|
|
10
11
|
const isSecondary = item.primary === undefined ? isEven : !item.primary;
|
|
11
12
|
const getPriceItem = () => {
|
|
@@ -14,5 +15,5 @@ export function InvoiceItemBlock({ item, index, layoutType }) {
|
|
|
14
15
|
}
|
|
15
16
|
return item.price !== undefined ? formatCurrency(item.price) : undefined;
|
|
16
17
|
};
|
|
17
|
-
return (_jsxs(_Fragment, { children: [item.topDivider && _jsx(Divider, {}), _jsxs("div", { className: styles.itemGrid, "data-discount": Boolean(item.discount), children: ['label' in item && item.label !== undefined && (_jsxs(_Fragment, { children: [_jsx("div", { className: styles.labelCell, "data-secondary": isSecondary, children: _jsx(InvoiceItemLabelCell, { item: item, layoutType: layoutType }) }), _jsx(Typography.SansBodyS, { tag: 'div', className: styles.priceCell, "data-secondary": isSecondary, children: getPriceItem() })] })), item.discount && (_jsxs(_Fragment, { children: [_jsx("div", { className: styles.percentCell, "data-secondary": isSecondary, children: _jsx(DiscountPercentCell, { discount: item.discount, layoutType: layoutType }) }), _jsx(Typography.SansBodyS, { tag: 'div', className: styles.discountCell, "data-secondary": isSecondary, children: formatCurrency(-Math.abs(item.discount.value)) })] }))] }), item.bottomDivider && _jsx(Divider, {})] }));
|
|
18
|
+
return (_jsxs(_Fragment, { children: [item.topDivider && _jsx(Divider, {}), item.coveredByGrant !== undefined && showCoveredByGrantLabel && (_jsx(CoveredByGrantLabel, { covered: item.coveredByGrant })), _jsxs("div", { className: styles.itemGrid, "data-discount": Boolean(item.discount), children: ['label' in item && item.label !== undefined && (_jsxs(_Fragment, { children: [_jsx("div", { className: styles.labelCell, "data-secondary": isSecondary, children: _jsx(InvoiceItemLabelCell, { item: item, layoutType: layoutType }) }), _jsx(Typography.SansBodyS, { tag: 'div', className: styles.priceCell, "data-secondary": isSecondary, children: getPriceItem() })] })), item.discount && (_jsxs(_Fragment, { children: [_jsx("div", { className: styles.percentCell, "data-secondary": isSecondary, children: _jsx(DiscountPercentCell, { discount: item.discount, layoutType: layoutType }) }), _jsx(Typography.SansBodyS, { tag: 'div', className: styles.discountCell, "data-secondary": isSecondary, children: formatCurrency(-Math.abs(item.discount.value)) })] }))] }), item.bottomDivider && _jsx(Divider, {})] }));
|
|
18
19
|
}
|
|
@@ -23,16 +23,24 @@ export type PriceInvoiceItem = {
|
|
|
23
23
|
export type DiscountInvoiceItem = {
|
|
24
24
|
discount: DiscountItem;
|
|
25
25
|
};
|
|
26
|
-
export type
|
|
26
|
+
export type BaseInvoiceItem = (PriceInvoiceItem | DiscountInvoiceItem) & {
|
|
27
27
|
labelTooltip?: QuestionTooltipProps['tip'];
|
|
28
28
|
price?: number;
|
|
29
29
|
hidePrice?: boolean;
|
|
30
30
|
labelMaxLines?: number;
|
|
31
31
|
quantity?: string | number;
|
|
32
|
-
primary?: boolean;
|
|
33
32
|
topDivider?: boolean;
|
|
34
33
|
bottomDivider?: boolean;
|
|
35
34
|
};
|
|
35
|
+
export type PrimaryInvoiceItem = BaseInvoiceItem & {
|
|
36
|
+
primary: true;
|
|
37
|
+
coveredByGrant?: boolean;
|
|
38
|
+
};
|
|
39
|
+
export type SecondaryInvoiceItem = BaseInvoiceItem & {
|
|
40
|
+
primary?: false;
|
|
41
|
+
coveredByGrant?: never;
|
|
42
|
+
};
|
|
43
|
+
export type InvoiceItem = PrimaryInvoiceItem | SecondaryInvoiceItem;
|
|
36
44
|
export type InvoiceDetails = {
|
|
37
45
|
title?: string;
|
|
38
46
|
quantity?: string | number;
|
package/package.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@cloud-ru/uikit-product-price-summary",
|
|
3
3
|
"title": "Price Summary",
|
|
4
|
-
"version": "2.0
|
|
4
|
+
"version": "2.1.0",
|
|
5
5
|
"sideEffects": [
|
|
6
6
|
"*.css",
|
|
7
7
|
"*.woff",
|
|
@@ -56,5 +56,5 @@
|
|
|
56
56
|
"peerDependencies": {
|
|
57
57
|
"@cloud-ru/uikit-product-locale": "*"
|
|
58
58
|
},
|
|
59
|
-
"gitHead": "
|
|
59
|
+
"gitHead": "bf43b88679e139965b4fde448011ed5bf1ca213d"
|
|
60
60
|
}
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import cn from 'classnames';
|
|
2
|
+
|
|
3
|
+
import { useLocale } from '@cloud-ru/uikit-product-locale';
|
|
4
|
+
import { PromoTag } from '@snack-uikit/promo-tag';
|
|
5
|
+
import { QuestionTooltip } from '@snack-uikit/tooltip';
|
|
6
|
+
|
|
7
|
+
import styles from './styles.module.scss';
|
|
8
|
+
|
|
9
|
+
export type CoveredByGrantLabelProps = {
|
|
10
|
+
covered: boolean;
|
|
11
|
+
className?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export function CoveredByGrantLabel({ covered, className }: CoveredByGrantLabelProps) {
|
|
15
|
+
const { t } = useLocale('PriceSummary');
|
|
16
|
+
return (
|
|
17
|
+
<div className={cn(styles.coveredByGrant, className)}>
|
|
18
|
+
<PromoTag
|
|
19
|
+
appearance={covered ? 'green' : 'neutral'}
|
|
20
|
+
color='decor'
|
|
21
|
+
text={covered ? t('coveredByGrant') : t('notCoveredByGrant')}
|
|
22
|
+
/>
|
|
23
|
+
<QuestionTooltip
|
|
24
|
+
tip={covered ? t('coveredByGrantTooltip') : t('notCoveredByGrantTooltip')}
|
|
25
|
+
size='xs'
|
|
26
|
+
placement='top'
|
|
27
|
+
trigger='hover'
|
|
28
|
+
tabIndex={-1}
|
|
29
|
+
/>
|
|
30
|
+
</div>
|
|
31
|
+
);
|
|
32
|
+
}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './CoveredByGrantLabel';
|
|
@@ -4,6 +4,7 @@ import { Typography } from '@snack-uikit/typography';
|
|
|
4
4
|
|
|
5
5
|
import { formatCurrency, formatQuantity } from '../../../../helpers';
|
|
6
6
|
import { InvoiceDetails } from '../../../../types';
|
|
7
|
+
import { CoveredByGrantLabel } from '../CoveredByGrantLabel';
|
|
7
8
|
import { Divider } from '../Divider';
|
|
8
9
|
import { InvoiceItemBlock } from '../InvoiceItemBlock';
|
|
9
10
|
import styles from './styles.module.scss';
|
|
@@ -15,8 +16,17 @@ export type InvoiceDetailsBlockProps = WithLayoutType<{
|
|
|
15
16
|
export function InvoiceDetailsBlock({ invoice, layoutType }: InvoiceDetailsBlockProps) {
|
|
16
17
|
const { t } = useLocale('PriceSummary');
|
|
17
18
|
|
|
19
|
+
const primaryItems = invoice.items.filter(item => item.primary);
|
|
20
|
+
const firstValue = primaryItems[0]?.coveredByGrant;
|
|
21
|
+
const allSameValue = primaryItems.length > 0 && primaryItems.every(item => item.coveredByGrant === firstValue);
|
|
22
|
+
|
|
23
|
+
const showBlockLabel = allSameValue && firstValue !== undefined;
|
|
24
|
+
const showItemLabels = !showBlockLabel;
|
|
25
|
+
|
|
18
26
|
return (
|
|
19
27
|
<div className={styles.main}>
|
|
28
|
+
{showBlockLabel && <CoveredByGrantLabel covered={firstValue} />}
|
|
29
|
+
|
|
20
30
|
{invoice.title && (
|
|
21
31
|
<>
|
|
22
32
|
<div className={styles.header}>
|
|
@@ -29,7 +39,13 @@ export function InvoiceDetailsBlock({ invoice, layoutType }: InvoiceDetailsBlock
|
|
|
29
39
|
)}
|
|
30
40
|
|
|
31
41
|
{invoice.items.map((item, index) => (
|
|
32
|
-
<InvoiceItemBlock
|
|
42
|
+
<InvoiceItemBlock
|
|
43
|
+
key={index}
|
|
44
|
+
item={item}
|
|
45
|
+
index={index}
|
|
46
|
+
layoutType={layoutType}
|
|
47
|
+
showCoveredByGrantLabel={showItemLabels}
|
|
48
|
+
/>
|
|
33
49
|
))}
|
|
34
50
|
|
|
35
51
|
{invoice.price !== undefined && (
|
|
@@ -3,6 +3,7 @@ import { Typography } from '@snack-uikit/typography';
|
|
|
3
3
|
|
|
4
4
|
import { formatCurrency } from '../../../../helpers';
|
|
5
5
|
import { InvoiceItem } from '../../../../types';
|
|
6
|
+
import { CoveredByGrantLabel } from '../CoveredByGrantLabel';
|
|
6
7
|
import { DiscountPercentCell } from '../DiscountPercentCell';
|
|
7
8
|
import { Divider } from '../Divider';
|
|
8
9
|
import { InvoiceItemLabelCell } from '../InvoiceItemLabelCell';
|
|
@@ -11,9 +12,10 @@ import styles from './styles.module.scss';
|
|
|
11
12
|
export type InvoiceItemBlockProps = WithLayoutType<{
|
|
12
13
|
item: InvoiceItem;
|
|
13
14
|
index: number;
|
|
15
|
+
showCoveredByGrantLabel?: boolean;
|
|
14
16
|
}>;
|
|
15
17
|
|
|
16
|
-
export function InvoiceItemBlock({ item, index, layoutType }: InvoiceItemBlockProps) {
|
|
18
|
+
export function InvoiceItemBlock({ item, index, layoutType, showCoveredByGrantLabel }: InvoiceItemBlockProps) {
|
|
17
19
|
const isEven = (index + 1) % 2 === 0;
|
|
18
20
|
|
|
19
21
|
const isSecondary = item.primary === undefined ? isEven : !item.primary;
|
|
@@ -30,6 +32,9 @@ export function InvoiceItemBlock({ item, index, layoutType }: InvoiceItemBlockPr
|
|
|
30
32
|
<>
|
|
31
33
|
{item.topDivider && <Divider />}
|
|
32
34
|
|
|
35
|
+
{item.coveredByGrant !== undefined && showCoveredByGrantLabel && (
|
|
36
|
+
<CoveredByGrantLabel covered={item.coveredByGrant} />
|
|
37
|
+
)}
|
|
33
38
|
<div className={styles.itemGrid} data-discount={Boolean(item.discount)}>
|
|
34
39
|
{'label' in item && item.label !== undefined && (
|
|
35
40
|
<>
|
package/src/types/index.ts
CHANGED
|
@@ -30,17 +30,28 @@ export type DiscountInvoiceItem = {
|
|
|
30
30
|
discount: DiscountItem;
|
|
31
31
|
};
|
|
32
32
|
|
|
33
|
-
export type
|
|
33
|
+
export type BaseInvoiceItem = (PriceInvoiceItem | DiscountInvoiceItem) & {
|
|
34
34
|
labelTooltip?: QuestionTooltipProps['tip'];
|
|
35
35
|
price?: number;
|
|
36
36
|
hidePrice?: boolean;
|
|
37
37
|
labelMaxLines?: number;
|
|
38
38
|
quantity?: string | number;
|
|
39
|
-
primary?: boolean;
|
|
40
39
|
topDivider?: boolean;
|
|
41
40
|
bottomDivider?: boolean;
|
|
42
41
|
};
|
|
43
42
|
|
|
43
|
+
export type PrimaryInvoiceItem = BaseInvoiceItem & {
|
|
44
|
+
primary: true;
|
|
45
|
+
coveredByGrant?: boolean;
|
|
46
|
+
};
|
|
47
|
+
|
|
48
|
+
export type SecondaryInvoiceItem = BaseInvoiceItem & {
|
|
49
|
+
primary?: false;
|
|
50
|
+
coveredByGrant?: never;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
export type InvoiceItem = PrimaryInvoiceItem | SecondaryInvoiceItem;
|
|
54
|
+
|
|
44
55
|
export type InvoiceDetails = {
|
|
45
56
|
title?: string;
|
|
46
57
|
quantity?: string | number;
|