@faststore/components 2.0.6-alpha.0 → 2.0.9-alpha.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 +18 -0
- package/dist/atoms/Price/Price.d.ts +28 -0
- package/dist/atoms/Price/Price.js +7 -0
- package/dist/atoms/Price/Price.js.map +1 -0
- package/dist/atoms/Price/index.d.ts +2 -0
- package/dist/atoms/Price/index.js +2 -0
- package/dist/atoms/Price/index.js.map +1 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +2 -0
- package/dist/index.js.map +1 -1
- package/dist/molecules/DiscountBadge/DiscountBadge.d.ts +25 -0
- package/dist/molecules/DiscountBadge/DiscountBadge.js +19 -0
- package/dist/molecules/DiscountBadge/DiscountBadge.js.map +1 -0
- package/dist/molecules/DiscountBadge/index.d.ts +2 -0
- package/dist/molecules/DiscountBadge/index.js +2 -0
- package/dist/molecules/DiscountBadge/index.js.map +1 -0
- package/dist/molecules/DiscountBadge/useDiscountPercent.d.ts +1 -0
- package/dist/molecules/DiscountBadge/useDiscountPercent.js +9 -0
- package/dist/molecules/DiscountBadge/useDiscountPercent.js.map +1 -0
- package/package.json +2 -2
- package/src/atoms/Price/Price.tsx +65 -0
- package/src/atoms/Price/index.ts +2 -0
- package/src/index.ts +4 -0
- package/src/molecules/DiscountBadge/DiscountBadge.tsx +60 -0
- package/src/molecules/DiscountBadge/index.ts +2 -0
- package/src/molecules/DiscountBadge/useDiscountPercent.ts +10 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,24 @@
|
|
|
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.0.9-alpha.0](https://github.com/vtex/faststore/compare/v2.0.8-alpha.0...v2.0.9-alpha.0) (2022-12-12)
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
### Features
|
|
10
|
+
|
|
11
|
+
* Create `Price` component ([#1548](https://github.com/vtex/faststore/issues/1548)) ([2d7418a](https://github.com/vtex/faststore/commit/2d7418ad45f42cdb0174d45d7c4de5b6d6e27f60))
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
## [2.0.7-alpha.0](https://github.com/vtex/faststore/compare/v2.0.6-alpha.0...v2.0.7-alpha.0) (2022-12-09)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
### Features
|
|
19
|
+
|
|
20
|
+
* Adds `DiscountBadge` component ([#1546](https://github.com/vtex/faststore/issues/1546)) ([9b2e279](https://github.com/vtex/faststore/commit/9b2e27940ffa9b52c9a62541a07e1f593a0bcfb7)), closes [#313](https://github.com/vtex/faststore/issues/313)
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
|
|
6
24
|
## [2.0.6-alpha.0](https://github.com/vtex/faststore/compare/v2.0.5-alpha.0...v2.0.6-alpha.0) (2022-12-08)
|
|
7
25
|
|
|
8
26
|
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
import type { HTMLAttributes, ElementType, ReactNode } from 'react';
|
|
2
|
+
import React from 'react';
|
|
3
|
+
export declare type PriceVariant = 'selling' | 'listing' | 'spot' | 'savings' | 'installment';
|
|
4
|
+
export declare type PriceFormatter = (price: number, variant: PriceVariant) => ReactNode;
|
|
5
|
+
export interface PriceProps extends Omit<HTMLAttributes<HTMLSpanElement>, 'children'> {
|
|
6
|
+
/**
|
|
7
|
+
* Set the HTML element tag of this component.
|
|
8
|
+
*/
|
|
9
|
+
as?: ElementType;
|
|
10
|
+
/**
|
|
11
|
+
* ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
|
|
12
|
+
*/
|
|
13
|
+
testId?: string;
|
|
14
|
+
/**
|
|
15
|
+
* The raw price value.
|
|
16
|
+
*/
|
|
17
|
+
value: number;
|
|
18
|
+
/**
|
|
19
|
+
* Formatter function that transforms the raw price value and render the result.
|
|
20
|
+
*/
|
|
21
|
+
formatter?: PriceFormatter;
|
|
22
|
+
/**
|
|
23
|
+
* The current use case variant for prices.
|
|
24
|
+
*/
|
|
25
|
+
variant?: PriceVariant;
|
|
26
|
+
}
|
|
27
|
+
declare const Price: React.ForwardRefExoticComponent<PriceProps & React.RefAttributes<Omit<HTMLSpanElement, "children">>>;
|
|
28
|
+
export default Price;
|
|
@@ -0,0 +1,7 @@
|
|
|
1
|
+
import React, { forwardRef } from 'react';
|
|
2
|
+
const Price = forwardRef(function Price({ value, as: Component = 'span', variant = 'selling', testId = 'fs-price', formatter = (price) => price, ...otherProps }, ref) {
|
|
3
|
+
const formattedPrice = formatter(value, variant);
|
|
4
|
+
return (React.createElement(Component, { ref: ref, "data-fs-price": true, "data-testid": testId, "data-fs-price-variant": variant, ...otherProps }, formattedPrice));
|
|
5
|
+
});
|
|
6
|
+
export default Price;
|
|
7
|
+
//# sourceMappingURL=Price.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Price.js","sourceRoot":"","sources":["../../../src/atoms/Price/Price.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,EAAE,UAAU,EAAE,MAAM,OAAO,CAAA;AAmCzC,MAAM,KAAK,GAAG,UAAU,CACtB,SAAS,KAAK,CACZ,EACE,KAAK,EACL,EAAE,EAAE,SAAS,GAAG,MAAM,EACtB,OAAO,GAAG,SAAS,EACnB,MAAM,GAAG,UAAU,EACnB,SAAS,GAAG,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,EAC5B,GAAG,UAAU,EACd,EACD,GAAG;IAEH,MAAM,cAAc,GAAG,SAAS,CAAC,KAAK,EAAE,OAAO,CAAC,CAAA;IAEhD,OAAO,CACL,oBAAC,SAAS,IACR,GAAG,EAAE,GAAG,wCAEK,MAAM,2BACI,OAAO,KAC1B,UAAU,IAEb,cAAc,CACL,CACb,CAAA;AACH,CAAC,CACF,CAAA;AAED,eAAe,KAAK,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/atoms/Price/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,SAAS,CAAA"}
|
package/dist/index.d.ts
CHANGED
|
@@ -12,12 +12,16 @@ export { default as Label } from './atoms/Label';
|
|
|
12
12
|
export type { LabelProps } from './atoms/Label';
|
|
13
13
|
export { default as Overlay } from './atoms/Overlay';
|
|
14
14
|
export type { OverlayProps } from './atoms/Overlay';
|
|
15
|
+
export { default as Price } from './atoms/Price';
|
|
16
|
+
export type { PriceProps } from './atoms/Price';
|
|
15
17
|
export { default as Radio } from './atoms/Radio';
|
|
16
18
|
export type { RadioProps } from './atoms/Radio';
|
|
17
19
|
export { default as CheckboxField } from './molecules/CheckboxField';
|
|
18
20
|
export type { CheckboxFieldProps } from './molecules/CheckboxField';
|
|
19
21
|
export { default as IconButton } from './molecules/IconButton';
|
|
20
22
|
export type { IconButtonProps } from './molecules/IconButton';
|
|
23
|
+
export { default as DiscountBadge } from './molecules/DiscountBadge';
|
|
24
|
+
export type { DiscountBadgeProps } from './molecules/DiscountBadge';
|
|
21
25
|
export { default as InputField } from './molecules/InputField';
|
|
22
26
|
export type { InputFieldProps } from './molecules/InputField';
|
|
23
27
|
export { default as RadioField } from './molecules/RadioField';
|
package/dist/index.js
CHANGED
|
@@ -6,10 +6,12 @@ export { default as Icon } from './atoms/Icon';
|
|
|
6
6
|
export { default as Input } from './atoms/Input';
|
|
7
7
|
export { default as Label } from './atoms/Label';
|
|
8
8
|
export { default as Overlay } from './atoms/Overlay';
|
|
9
|
+
export { default as Price } from './atoms/Price';
|
|
9
10
|
export { default as Radio } from './atoms/Radio';
|
|
10
11
|
// Molecules
|
|
11
12
|
export { default as CheckboxField } from './molecules/CheckboxField';
|
|
12
13
|
export { default as IconButton } from './molecules/IconButton';
|
|
14
|
+
export { default as DiscountBadge } from './molecules/DiscountBadge';
|
|
13
15
|
export { default as InputField } from './molecules/InputField';
|
|
14
16
|
export { default as RadioField } from './molecules/RadioField';
|
|
15
17
|
export { default as Tag } from './molecules/Tag';
|
package/dist/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAElD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAEtD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,cAAc,CAAA;AAE9C,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAEpD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,eAAe,CAAA;AAGhD,YAAY;AACZ,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAEpE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAE9D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAE9D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAE9D,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,iBAAiB,CAAA"}
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.ts"],"names":[],"mappings":"AAAA,QAAQ;AACR,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,EAAE,OAAO,IAAI,MAAM,EAAE,MAAM,gBAAgB,CAAA;AAElD,OAAO,EAAE,OAAO,IAAI,QAAQ,EAAE,MAAM,kBAAkB,CAAA;AAEtD,OAAO,EAAE,OAAO,IAAI,IAAI,EAAE,MAAM,cAAc,CAAA;AAE9C,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,EAAE,OAAO,IAAI,OAAO,EAAE,MAAM,iBAAiB,CAAA;AAEpD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,eAAe,CAAA;AAEhD,OAAO,EAAE,OAAO,IAAI,KAAK,EAAE,MAAM,eAAe,CAAA;AAGhD,YAAY;AACZ,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAEpE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAE9D,OAAO,EAAE,OAAO,IAAI,aAAa,EAAE,MAAM,2BAA2B,CAAA;AAEpE,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAE9D,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,wBAAwB,CAAA;AAE9D,OAAO,EAAE,OAAO,IAAI,GAAG,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
/// <reference types="react" />
|
|
2
|
+
export declare type DiscountBadgeProps = {
|
|
3
|
+
/**
|
|
4
|
+
* Specifies price without discount applied.
|
|
5
|
+
*/
|
|
6
|
+
listPrice: number;
|
|
7
|
+
/**
|
|
8
|
+
* Specifies current price with discount applied.
|
|
9
|
+
*/
|
|
10
|
+
spotPrice: number;
|
|
11
|
+
/**
|
|
12
|
+
* Sets the component's size.
|
|
13
|
+
*/
|
|
14
|
+
size?: 'small' | 'big';
|
|
15
|
+
/**
|
|
16
|
+
* Sets the limit percentage value to consider a low discount.
|
|
17
|
+
*/
|
|
18
|
+
thresholdLow?: number;
|
|
19
|
+
/**
|
|
20
|
+
* Sets the limit percentage value to consider a high discount.
|
|
21
|
+
*/
|
|
22
|
+
thresholdHigh?: number;
|
|
23
|
+
};
|
|
24
|
+
declare const DiscountBadge: ({ listPrice, spotPrice, size, thresholdLow, thresholdHigh, }: DiscountBadgeProps) => JSX.Element;
|
|
25
|
+
export default DiscountBadge;
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { Badge } from '../..';
|
|
3
|
+
import { useDiscountPercent } from '../DiscountBadge/useDiscountPercent';
|
|
4
|
+
const DiscountBadge = ({ listPrice, spotPrice, size = 'small', thresholdLow = 15, thresholdHigh = 40, }) => {
|
|
5
|
+
const discountPercent = useDiscountPercent(listPrice, spotPrice);
|
|
6
|
+
if (discountPercent === 0) {
|
|
7
|
+
return React.createElement(React.Fragment, null);
|
|
8
|
+
}
|
|
9
|
+
const discountVariant = discountPercent <= thresholdLow
|
|
10
|
+
? 'low'
|
|
11
|
+
: discountPercent <= thresholdHigh
|
|
12
|
+
? 'medium'
|
|
13
|
+
: 'high';
|
|
14
|
+
return (React.createElement(Badge, { size: size, "data-fs-discount-badge": true, "data-fs-discount-badge-variant": discountVariant },
|
|
15
|
+
discountPercent,
|
|
16
|
+
"% off"));
|
|
17
|
+
};
|
|
18
|
+
export default DiscountBadge;
|
|
19
|
+
//# sourceMappingURL=DiscountBadge.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"DiscountBadge.js","sourceRoot":"","sources":["../../../src/molecules/DiscountBadge/DiscountBadge.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAA;AACzB,OAAO,EAAE,KAAK,EAAE,MAAM,OAAO,CAAA;AAE7B,OAAO,EAAE,kBAAkB,EAAE,MAAM,qCAAqC,CAAA;AAyBxE,MAAM,aAAa,GAAG,CAAC,EACrB,SAAS,EACT,SAAS,EACT,IAAI,GAAG,OAAO,EACd,YAAY,GAAG,EAAE,EACjB,aAAa,GAAG,EAAE,GACC,EAAE,EAAE;IACvB,MAAM,eAAe,GAAG,kBAAkB,CAAC,SAAS,EAAE,SAAS,CAAC,CAAA;IAEhE,IAAI,eAAe,KAAK,CAAC,EAAE;QACzB,OAAO,yCAAK,CAAA;KACb;IAED,MAAM,eAAe,GACnB,eAAe,IAAI,YAAY;QAC7B,CAAC,CAAC,KAAK;QACP,CAAC,CAAC,eAAe,IAAI,aAAa;YAClC,CAAC,CAAC,QAAQ;YACV,CAAC,CAAC,MAAM,CAAA;IAEZ,OAAO,CACL,oBAAC,KAAK,IACJ,IAAI,EAAE,IAAI,oEAEsB,eAAe;QAE9C,eAAe;gBACV,CACT,CAAA;AACH,CAAC,CAAA;AAED,eAAe,aAAa,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"index.js","sourceRoot":"","sources":["../../../src/molecules/DiscountBadge/index.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,iBAAiB,CAAA"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export declare const useDiscountPercent: (listPrice: number, spotPrice: number) => number;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
import { useMemo } from 'react';
|
|
2
|
+
export const useDiscountPercent = (listPrice, spotPrice) => {
|
|
3
|
+
return useMemo(() => {
|
|
4
|
+
const diff = listPrice - spotPrice;
|
|
5
|
+
const discount = (diff * 100) / listPrice;
|
|
6
|
+
return Math.round(discount);
|
|
7
|
+
}, [spotPrice, listPrice]);
|
|
8
|
+
};
|
|
9
|
+
//# sourceMappingURL=useDiscountPercent.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDiscountPercent.js","sourceRoot":"","sources":["../../../src/molecules/DiscountBadge/useDiscountPercent.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,OAAO,EAAE,MAAM,OAAO,CAAA;AAE/B,MAAM,CAAC,MAAM,kBAAkB,GAAG,CAAC,SAAiB,EAAE,SAAiB,EAAE,EAAE;IACzE,OAAO,OAAO,CAAC,GAAG,EAAE;QAClB,MAAM,IAAI,GAAG,SAAS,GAAG,SAAS,CAAA;QAClC,MAAM,QAAQ,GAAG,CAAC,IAAI,GAAG,GAAG,CAAC,GAAG,SAAS,CAAA;QAEzC,OAAO,IAAI,CAAC,KAAK,CAAC,QAAQ,CAAC,CAAA;IAC7B,CAAC,EAAE,CAAC,SAAS,EAAE,SAAS,CAAC,CAAC,CAAA;AAC5B,CAAC,CAAA"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@faststore/components",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.9-alpha.0",
|
|
4
4
|
"module": "dist/index.js",
|
|
5
5
|
"typings": "dist/index.d.ts",
|
|
6
6
|
"author": "Emerson Laurentino @emersonlaurentino",
|
|
@@ -28,5 +28,5 @@
|
|
|
28
28
|
"node": "16.18.0",
|
|
29
29
|
"yarn": "1.19.1"
|
|
30
30
|
},
|
|
31
|
-
"gitHead": "
|
|
31
|
+
"gitHead": "df3ddd2d140bf19046a4753474bebee4298cd6ac"
|
|
32
32
|
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import type { HTMLAttributes, ElementType, ReactNode } from 'react'
|
|
2
|
+
import React, { forwardRef } from 'react'
|
|
3
|
+
|
|
4
|
+
export type PriceVariant =
|
|
5
|
+
| 'selling'
|
|
6
|
+
| 'listing'
|
|
7
|
+
| 'spot'
|
|
8
|
+
| 'savings'
|
|
9
|
+
| 'installment'
|
|
10
|
+
|
|
11
|
+
export type PriceFormatter = (price: number, variant: PriceVariant) => ReactNode
|
|
12
|
+
|
|
13
|
+
export interface PriceProps
|
|
14
|
+
extends Omit<HTMLAttributes<HTMLSpanElement>, 'children'> {
|
|
15
|
+
/**
|
|
16
|
+
* Set the HTML element tag of this component.
|
|
17
|
+
*/
|
|
18
|
+
as?: ElementType
|
|
19
|
+
/**
|
|
20
|
+
* ID to find this component in testing tools (e.g.: cypress, testing library, and jest).
|
|
21
|
+
*/
|
|
22
|
+
testId?: string
|
|
23
|
+
/**
|
|
24
|
+
* The raw price value.
|
|
25
|
+
*/
|
|
26
|
+
value: number
|
|
27
|
+
/**
|
|
28
|
+
* Formatter function that transforms the raw price value and render the result.
|
|
29
|
+
*/
|
|
30
|
+
formatter?: PriceFormatter
|
|
31
|
+
/**
|
|
32
|
+
* The current use case variant for prices.
|
|
33
|
+
*/
|
|
34
|
+
variant?: PriceVariant
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
const Price = forwardRef<Omit<HTMLSpanElement, 'children'>, PriceProps>(
|
|
38
|
+
function Price(
|
|
39
|
+
{
|
|
40
|
+
value,
|
|
41
|
+
as: Component = 'span',
|
|
42
|
+
variant = 'selling',
|
|
43
|
+
testId = 'fs-price',
|
|
44
|
+
formatter = (price) => price,
|
|
45
|
+
...otherProps
|
|
46
|
+
},
|
|
47
|
+
ref
|
|
48
|
+
) {
|
|
49
|
+
const formattedPrice = formatter(value, variant)
|
|
50
|
+
|
|
51
|
+
return (
|
|
52
|
+
<Component
|
|
53
|
+
ref={ref}
|
|
54
|
+
data-fs-price
|
|
55
|
+
data-testid={testId}
|
|
56
|
+
data-fs-price-variant={variant}
|
|
57
|
+
{...otherProps}
|
|
58
|
+
>
|
|
59
|
+
{formattedPrice}
|
|
60
|
+
</Component>
|
|
61
|
+
)
|
|
62
|
+
}
|
|
63
|
+
)
|
|
64
|
+
|
|
65
|
+
export default Price
|
package/src/index.ts
CHANGED
|
@@ -13,6 +13,8 @@ export { default as Label } from './atoms/Label'
|
|
|
13
13
|
export type { LabelProps } from './atoms/Label'
|
|
14
14
|
export { default as Overlay } from './atoms/Overlay'
|
|
15
15
|
export type { OverlayProps } from './atoms/Overlay'
|
|
16
|
+
export { default as Price } from './atoms/Price'
|
|
17
|
+
export type { PriceProps } from './atoms/Price'
|
|
16
18
|
export { default as Radio } from './atoms/Radio'
|
|
17
19
|
export type { RadioProps } from './atoms/Radio'
|
|
18
20
|
|
|
@@ -21,6 +23,8 @@ export { default as CheckboxField } from './molecules/CheckboxField'
|
|
|
21
23
|
export type { CheckboxFieldProps } from './molecules/CheckboxField'
|
|
22
24
|
export { default as IconButton } from './molecules/IconButton'
|
|
23
25
|
export type { IconButtonProps } from './molecules/IconButton'
|
|
26
|
+
export { default as DiscountBadge } from './molecules/DiscountBadge'
|
|
27
|
+
export type { DiscountBadgeProps } from './molecules/DiscountBadge'
|
|
24
28
|
export { default as InputField } from './molecules/InputField'
|
|
25
29
|
export type { InputFieldProps } from './molecules/InputField'
|
|
26
30
|
export { default as RadioField } from './molecules/RadioField'
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
import { Badge } from '../..'
|
|
3
|
+
|
|
4
|
+
import { useDiscountPercent } from '../DiscountBadge/useDiscountPercent'
|
|
5
|
+
|
|
6
|
+
export type DiscountBadgeProps = {
|
|
7
|
+
/**
|
|
8
|
+
* Specifies price without discount applied.
|
|
9
|
+
*/
|
|
10
|
+
listPrice: number
|
|
11
|
+
/**
|
|
12
|
+
* Specifies current price with discount applied.
|
|
13
|
+
*/
|
|
14
|
+
spotPrice: number
|
|
15
|
+
/**
|
|
16
|
+
* Sets the component's size.
|
|
17
|
+
*/
|
|
18
|
+
size?: 'small' | 'big'
|
|
19
|
+
/**
|
|
20
|
+
* Sets the limit percentage value to consider a low discount.
|
|
21
|
+
*/
|
|
22
|
+
thresholdLow?: number
|
|
23
|
+
/**
|
|
24
|
+
* Sets the limit percentage value to consider a high discount.
|
|
25
|
+
*/
|
|
26
|
+
thresholdHigh?: number
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
const DiscountBadge = ({
|
|
30
|
+
listPrice,
|
|
31
|
+
spotPrice,
|
|
32
|
+
size = 'small',
|
|
33
|
+
thresholdLow = 15,
|
|
34
|
+
thresholdHigh = 40,
|
|
35
|
+
}: DiscountBadgeProps) => {
|
|
36
|
+
const discountPercent = useDiscountPercent(listPrice, spotPrice)
|
|
37
|
+
|
|
38
|
+
if (discountPercent === 0) {
|
|
39
|
+
return <></>
|
|
40
|
+
}
|
|
41
|
+
|
|
42
|
+
const discountVariant =
|
|
43
|
+
discountPercent <= thresholdLow
|
|
44
|
+
? 'low'
|
|
45
|
+
: discountPercent <= thresholdHigh
|
|
46
|
+
? 'medium'
|
|
47
|
+
: 'high'
|
|
48
|
+
|
|
49
|
+
return (
|
|
50
|
+
<Badge
|
|
51
|
+
size={size}
|
|
52
|
+
data-fs-discount-badge
|
|
53
|
+
data-fs-discount-badge-variant={discountVariant}
|
|
54
|
+
>
|
|
55
|
+
{discountPercent}% off
|
|
56
|
+
</Badge>
|
|
57
|
+
)
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
export default DiscountBadge
|
|
@@ -0,0 +1,10 @@
|
|
|
1
|
+
import { useMemo } from 'react'
|
|
2
|
+
|
|
3
|
+
export const useDiscountPercent = (listPrice: number, spotPrice: number) => {
|
|
4
|
+
return useMemo(() => {
|
|
5
|
+
const diff = listPrice - spotPrice
|
|
6
|
+
const discount = (diff * 100) / listPrice
|
|
7
|
+
|
|
8
|
+
return Math.round(discount)
|
|
9
|
+
}, [spotPrice, listPrice])
|
|
10
|
+
}
|