@bytebrand/fe-ui-core 4.2.51 → 4.2.53

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.
Files changed (21) hide show
  1. package/__tests__/components/UserDasboardPage/sections/OrderStatusSection/OrderStatusCard.test.tsx +39 -0
  2. package/__tests__/components/_common/{Badge.test.tsx → Badge/Badge.test.tsx} +1 -1
  3. package/jest.config.js +5 -4
  4. package/package.json +5 -2
  5. package/source/components/SearchPage/Filters/MakeModel/MakeModel.tsx +1 -1
  6. package/source/components/UserDashboardPage/sections/OrderStatusSection/AdditionalOrderInfo.styl +73 -0
  7. package/source/components/UserDashboardPage/sections/OrderStatusSection/AdditionalOrderInfo.tsx +89 -0
  8. package/source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusCar.tsx +125 -0
  9. package/source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusCard.styl +54 -0
  10. package/source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusCard.tsx +41 -0
  11. package/source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusSection.story.js +63 -0
  12. package/source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusSection.styl +167 -0
  13. package/source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusSection.tsx +128 -0
  14. package/source/components/VehicleSmallCard/VehicleData/VehiclePrice/VehiclePrice.tsx +1 -2
  15. package/source/components/VehicleSmallCard/VehicleSmallCard.tsx +1 -1
  16. package/source/components/_common/IconSVG/IconSVG.tsx +1 -1
  17. package/source/components/_common/MaterialField/MaterialField.tsx +6 -3
  18. package/source/components/_common/VehicleSlider/VehicleSliderForSRL.tsx +3 -4
  19. package/source/components/_common/withStats/withStats.tsx +3 -3
  20. package/source/components/containers/DasboardSection/DashboardSection.styl +15 -0
  21. package/source/components/containers/DasboardSection/DashboardSection.tsx +23 -0
@@ -0,0 +1,39 @@
1
+ import React from 'react';
2
+ import { render } from '@testing-library/react';
3
+ import OrderStatusCard from '../../../../../source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusCard';
4
+
5
+ describe('OrderStatusCard', () => {
6
+ const icon = 'orderReceivedDashboard';
7
+ const title = 'Test title';
8
+ const description = 'Test description';
9
+ it('renders a card with title, description, and icon', () => {
10
+ const { getByText, container, debug } = render(
11
+ <OrderStatusCard
12
+ icon={icon}
13
+ title={title}
14
+ description={description}
15
+ />
16
+ );
17
+ debug();
18
+ const cardTitle = getByText(title);
19
+ expect(cardTitle).toBeInTheDocument();
20
+ const cardDescription = getByText(description);
21
+ expect(cardDescription).toBeInTheDocument();
22
+ const svgElement = container.querySelector('svg');
23
+ expect(svgElement).toBeInTheDocument();
24
+ });
25
+
26
+ it('adds "isDisabled" class when isDisabled prop is set', () => {
27
+ const { getByTestId, debug } = render(
28
+ <OrderStatusCard
29
+ icon={icon}
30
+ title={title}
31
+ description={description}
32
+ isDisabled={true}
33
+ />
34
+ );
35
+ debug();
36
+ const cardTitle = getByTestId('cardTitle');
37
+ expect(cardTitle).toHaveClass('notReachedTitle');
38
+ });
39
+ });
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { render } from '@testing-library/react';
3
- import Badge from '../../../source/components/_common/Badge/Badge';
3
+ import Badge from '../../../../source/components/_common/Badge/Badge';
4
4
 
5
5
  describe('Badge', () => {
6
6
  const textToRender = 'Test Text';
package/jest.config.js CHANGED
@@ -8,8 +8,9 @@ module.exports = {
8
8
  ],
9
9
  transform: {
10
10
  "^.+\.(ts|tsx)?$": "ts-jest",
11
- ".+\\.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "jest-transform-stub",
12
- "^.+\\.svg$": "jest-svg-transformer"
11
+ ".+\\.(css|less|sass|scss|png|jpg|ttf|woff|woff2)$": "jest-transform-stub",
12
+ "^.+\\.svg$": "jest-svg-transformer",
13
+ '\\.(styl)$': '<rootDir>/node_modules/jest-stylus',
13
14
  },
14
15
  transformIgnorePatterns: [
15
16
  "node_modules/(?!@ngrx|(?!deck.gl)|ng-dynamic)",
@@ -23,9 +24,9 @@ module.exports = {
23
24
  "/public/"
24
25
  ],
25
26
  moduleNameMapper: {
26
- "^.+.(css|styl|less|sass|scss|png|jpg|ttf|woff|woff2)$": "jest-transform-stub",
27
+ "^.+.(css|less|sass|scss|png|jpg|ttf|woff|woff2)$": "jest-transform-stub",
27
28
  "^.+\\.svg$": "jest-svg-transformer",
28
- "\\.(css|less|scss|sss|styl)$": "<rootDir>/node_modules/jest-css-modules",
29
+ '\\.(styl)$': 'identity-obj-proxy',
29
30
  'react-dom/client': 'react-dom'
30
31
  },
31
32
  moduleFileExtensions: [
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytebrand/fe-ui-core",
3
- "version": "4.2.51",
3
+ "version": "4.2.53",
4
4
  "description": "UI components for the auto.de project",
5
5
  "main": "index.ts",
6
6
  "module": "dist/common.js",
@@ -39,9 +39,12 @@
39
39
  "date-fns": "2.29.1",
40
40
  "i18next": "^15.0.4",
41
41
  "jest": "^26.0.0",
42
+ "jest-css-modules": "^2.1.0",
43
+ "jest-css-modules-transform": "^4.4.2",
44
+ "jest-dom": "^4.0.0",
42
45
  "jest-environment-jsdom-sixteen": "^2.0.0",
46
+ "jest-stylus": "^0.1.2",
43
47
  "jest-svg-transformer": "^1.0.0",
44
- "jest-dom": "^4.0.0",
45
48
  "jest-transform-stub": "^2.0.0",
46
49
  "js-cookie": "^2.2.0",
47
50
  "moment": "^2.29.1",
@@ -59,7 +59,7 @@ class MakeModel extends React.Component<IMakeModelProps> {
59
59
 
60
60
  debaunceOnFilterChange = _debounce( // is used for the text field to add a delay and not make a search request for each key stroke
61
61
  (name: string, value: string, index: number) => {
62
- this.props.onChange(name, value, index)
62
+ this.props.onChange(name, value, index);
63
63
  },
64
64
  DEBOUNCE_TIME
65
65
  );
@@ -0,0 +1,73 @@
1
+ @import '../../../../theme/theme.styl'
2
+ @import '../../../../theme/mixins.styl'
3
+
4
+ .container
5
+ padding: 8px 8px 16px
6
+ border-top: 1px solid rgba(76,78,100,0.12)
7
+ +media-tablet-landscape-up()
8
+ padding: 12px 16px
9
+ display: grid
10
+ grid-template-columns: 1fr 1fr
11
+ column-gap: 32px
12
+
13
+ +media-tablet-landscape-up()
14
+ .orderInfoSection:first-child
15
+ position: relative
16
+
17
+ .orderInfoSection:first-child:after
18
+ content: ''
19
+ width: 1px
20
+ height: 100%
21
+ background-color: rgba(76,78,100,0.12)
22
+ display: block;
23
+ position: absolute;
24
+ top: 0;
25
+ right: -16px;
26
+
27
+ .labelText
28
+ color: $black50
29
+ font-size: 14px
30
+ line-height: 20px
31
+
32
+ .orderInfoAddresses
33
+ padding-bottom: 8px
34
+
35
+ .orderInfoPrice
36
+ border-top: 1px solid rgba(76,78,100,0.12)
37
+
38
+ .overallRateLabel
39
+ @extend .labelText
40
+ font-weight: bold
41
+
42
+ .flexContainer
43
+ display: flex
44
+ justify-content: space-between
45
+ align-items: center
46
+ margin-top: 8px
47
+
48
+ .customerSuport
49
+ @extend .labelText
50
+ text-align: center
51
+ margin-top: 8px
52
+ padding: 16px 24px
53
+ border-top: 1px solid rgba(76,78,100,0.12)
54
+
55
+ .customerSuportButton
56
+ margin-top: 8px
57
+ color: #26C6F9 !important
58
+ border-color: #26C6F9 !important
59
+ border-radius: 8px !important
60
+
61
+ .totalPrice
62
+ font-size: 24px
63
+ display: flex
64
+
65
+ .decimals
66
+ font-size: 24px !important
67
+ top: 7px !important
68
+
69
+ .unit
70
+ font-size: 14px
71
+
72
+ .montlyUnit
73
+ font-size: 8px
@@ -0,0 +1,89 @@
1
+ import React from 'react';
2
+ import styles from './AdditionalOrderInfo.styl';
3
+
4
+ import i18n from 'i18next';
5
+
6
+ import VehicleFormattedPrice from '../../../Vehicle/VehicleFormattedPrice/VehicleFormattedPrice';
7
+ import Button from '../../../_common/Button/Button';
8
+ import classNames from 'classnames';
9
+
10
+ interface IAdditionalOrderData {
11
+ addressData: { label: string, value: string }[];
12
+ carPriceData: { label: string, value: string }[];
13
+ financingData: { label: string, value: string }[];
14
+ overallRate: {
15
+ label: string,
16
+ value: number
17
+ };
18
+ }
19
+
20
+ interface IAdditionalOrderInfo {
21
+ t: i18n.TFunction;
22
+ additionalOrderData: IAdditionalOrderData;
23
+ }
24
+
25
+ const AdditionalOrderInfo = ({ t, additionalOrderData }: IAdditionalOrderInfo) => {
26
+ const { addressData, carPriceData, financingData, overallRate } = additionalOrderData;
27
+ return (
28
+ <div className={styles.container}>
29
+ <div className={styles.orderInfoSection}>
30
+ <div className={styles.orderInfoAddresses}>
31
+ {addressData.map((data) => {
32
+ const { value, label } = data;
33
+ return (
34
+ <div key={label}>
35
+ <div className={styles.labelText}>{label}</div>
36
+ <div className={styles.labelText}>{value}</div>
37
+ </div>
38
+ );
39
+ })}
40
+ </div>
41
+ <div className={styles.orderInfoPrice}>
42
+ {carPriceData.map((data) => {
43
+ const { value, label } = data;
44
+ return (
45
+ <div className={styles.flexContainer} key={label}>
46
+ <div className={styles.labelText}>{label}</div>
47
+ <div className={styles.labelText}>{value}</div>
48
+ </div>
49
+ );
50
+ })}
51
+ </div>
52
+ </div>
53
+ <div className={styles.orderInfoSection}>
54
+ <div className={styles.orderInfoFinancing}>
55
+ {financingData.map((data) => {
56
+ const { value, label } = data;
57
+ return (
58
+ <div className={styles.flexContainer} key={label}>
59
+ <div className={styles.labelText}>{label}</div>
60
+ <div className={styles.labelText}>{value}</div>
61
+ </div>
62
+ );
63
+ })}
64
+ <div className={classNames(styles.flexContainer, styles.overallRate)}>
65
+ <div className={styles.overallRateLabel}>{overallRate.label}</div>
66
+ <div>
67
+ <VehicleFormattedPrice
68
+ price={overallRate.value}
69
+ numbersAfterDot={2}
70
+ isNew
71
+ monthly='mtl'
72
+ className={styles.totalPrice}
73
+ afterCommaClassName={styles.decimals}
74
+ unitClassName={styles.unit}
75
+ monthlyClassName={styles.montlyUnit}
76
+ />
77
+ </div>
78
+ </div>
79
+ </div>
80
+ <div className={styles.customerSuport}>
81
+ <div>{t('customerSupportText')}</div>
82
+ <Button className={styles.customerSuportButton} variant='outlined'>{t('customerSupport')}</Button>
83
+ </div>
84
+ </div>
85
+ </div>
86
+ );
87
+ };
88
+
89
+ export default AdditionalOrderInfo;
@@ -0,0 +1,125 @@
1
+ import React, { useRef, useEffect, useState } from 'react';
2
+ import styles from './OrderStatusSection.styl';
3
+ import OrderStatusCard from './OrderStatusCard';
4
+ import i18n from 'i18next';
5
+ import Image from '../../../_common/Image/Image';
6
+ import { getFormattedPrice } from '../../../../framework/utils/CommonUtils';
7
+
8
+ interface IOrderStatusCar {
9
+ make?: string;
10
+ model?: string;
11
+ subModel?: string;
12
+ buyingType?: string;
13
+ imageUrl?: string;
14
+ selfPickup?: boolean;
15
+ paybackPeriod?: number;
16
+ monthlyInstallment?: number;
17
+ status?: string;
18
+ t: i18n.TFunction;
19
+ request: string;
20
+ registration: boolean;
21
+ currentSalesPrice: number;
22
+ onClick: () => void;
23
+ }
24
+
25
+ const OrderStatusCar = ({
26
+ make,
27
+ model,
28
+ subModel,
29
+ buyingType,
30
+ selfPickup,
31
+ paybackPeriod,
32
+ monthlyInstallment,
33
+ imageUrl,
34
+ status,
35
+ t,
36
+ request,
37
+ registration,
38
+ currentSalesPrice,
39
+ onClick
40
+ }: IOrderStatusCar) => {
41
+ const ref = useRef(null);
42
+ const [activeStep, setActiveStep] = useState(0); // 0 - when we have no active steps
43
+
44
+ const cardItems = [
45
+ { icon: 'orderReceivedDashboard', selector: 'selector_status_order_received' },
46
+ { icon: 'preparaionDashboard', selector: 'selector_status_preparation' },
47
+ { icon: 'registrationDashboard', selector: 'selector_status_registration' },
48
+ selfPickup ? { icon: 'pickupDashboard', selector: 'selector_status_pick_up' }
49
+ : { icon: 'deliveryDashboard', selector: 'selector_status_delivery' },
50
+ { icon: 'handingOverDashboard', selector: 'selector_status_handing_over' }
51
+ ];
52
+
53
+ useEffect(
54
+ () => {
55
+ cardItems.map((step, index) => {
56
+ const { selector } = step;
57
+ if (selector === status) {
58
+ setActiveStep(index + 1);
59
+ }
60
+ });
61
+ if (ref && ref.current) {
62
+ ref.current.parentElement.scrollBy({
63
+ top: 0,
64
+ left: 156 * activeStep,
65
+ behavior: 'smooth'
66
+ });
67
+ }
68
+ },
69
+ []
70
+ );
71
+
72
+ return (
73
+ <div className={styles.orderedCar}>
74
+ <div className={styles.orderReceivedSection}>
75
+ <div className={styles.carCardWrapper} onClick={onClick}>
76
+ <div className={styles.carCard}>
77
+ <div className={styles.carMarke}>
78
+ {make} {model}
79
+ </div>
80
+ <div className={styles.carCharacteristics}>
81
+ {subModel}
82
+ </div>
83
+ <div className={styles.carImg}>
84
+ {/* <Image className={styles.carImg} width='100%' ratioW={4} ratioH={3} src={imageUrl} /> */}
85
+ <img src={imageUrl}/>
86
+ </div>
87
+ <div className={styles.requestId}>{request}</div>
88
+ <div className={styles.carPayment} >
89
+ {t(`buyingType.${buyingType}`)},&nbsp;
90
+ {buyingType !== 'buy' && `${t('paybackPeriod', { paybackPeriod })},`}&nbsp;
91
+ {buyingType === 'buy' ?
92
+ t('currentSalesPrice', { currentSalesPrice: getFormattedPrice(currentSalesPrice) })
93
+ : t('monthlyInstallment', { monthlyInstallment: getFormattedPrice(monthlyInstallment, '$,.2f') })
94
+ }
95
+ </div>
96
+ </div>
97
+ </div>
98
+ <div className={styles.cardsSection}>
99
+ {cardItems.map((card, index) => {
100
+ const { icon, selector } = card;
101
+
102
+ const statusDescription = !registration && index === 2 ?
103
+ t('orderStatus.independentRegistration') :
104
+ t(`orderStatus.${selector}_desc`);
105
+
106
+ return (
107
+ <OrderStatusCard
108
+ cardRef={selector === status ? ref : null}
109
+ title={t(`orderStatus.${selector}`)}
110
+ description={statusDescription}
111
+ icon={icon}
112
+ key={index}
113
+ isActive={index + 1 === activeStep}
114
+ isDisabled={index + 1 > activeStep}
115
+ isDone={index + 1 < activeStep}
116
+ />
117
+ );
118
+ })}
119
+ </div>
120
+ </div>
121
+ </div>
122
+ );
123
+ };
124
+
125
+ export default OrderStatusCar;
@@ -0,0 +1,54 @@
1
+ @import '../../../../theme/mixins.styl'
2
+
3
+ .orderReceivedCardContainer
4
+ display: flex
5
+ align-items: center
6
+ border: 1px solid rgba(102, 108, 255, 0)
7
+
8
+ .orderReceivedCard
9
+ width: 156px
10
+ text-align: center
11
+ display: grid
12
+ grid-template-rows: 132px 25px 60px
13
+ grid-row-gap: 5px
14
+ justify-content: center
15
+ align-items: center
16
+ border-radius: 8px
17
+ padding: 5px 10px 0
18
+ box-sizing: border-box
19
+ height: fit-content
20
+
21
+ .cardInProgress
22
+ border: 1px solid rgba(102, 108, 255, 0.5)
23
+
24
+ .orderStatusTitle
25
+ display: inline-block
26
+ font-size: 12px
27
+ line-height: 20px
28
+ letter-spacing: 0.14px
29
+ color: #005CCB;
30
+ background: linear-gradient(0deg, rgba(255, 255, 255, 0.88), rgba(255, 255, 255, 0.88)), #666CFF
31
+ background-color:#666CFF
32
+ border-radius: 64px
33
+ padding: 0 6.5px
34
+ width: max-content
35
+ margin: 0 auto
36
+
37
+ .orderStatusDesc
38
+ font-size: 12px
39
+ line-height: 20px
40
+ text-align: left
41
+ color: rgba(76, 78, 100, 0.87)
42
+ margin: 0 auto
43
+ height: 100%
44
+
45
+ .cardIcon
46
+ display: block
47
+
48
+ .isDoneTitle
49
+ background: #00B800
50
+ color: #fff
51
+
52
+ .notReachedTitle
53
+ background: linear-gradient(0deg, rgba(255, 255, 255, 0.88), rgba(255, 255, 255, 0.88)), #26C6F9
54
+ color: #26C6F9
@@ -0,0 +1,41 @@
1
+ import React from 'react';
2
+ import IconSVG from '../../../_common/IconSVG/IconSVG';
3
+ import styles from './OrderStatusCard.styl';
4
+ import classnames from 'classnames';
5
+
6
+ interface IOrderStatusCard {
7
+ icon?: string;
8
+ title?: string;
9
+ description?: string;
10
+ isDisabled?: boolean;
11
+ cardRef?: any;
12
+ isActive?: boolean;
13
+ isDone?: boolean;
14
+ }
15
+
16
+ const OrderStatusCard = ({ icon, title, description, isDisabled, cardRef, isActive, isDone }: IOrderStatusCard) => {
17
+ const orderReceivedCardClasses = classnames(
18
+ styles.orderReceivedCard,
19
+ { [styles.cardInProgress]: isActive }
20
+ );
21
+
22
+ const orderStatusTitleClasses = classnames(
23
+ styles.orderStatusTitle,
24
+ { [styles.isDoneTitle]: isDone },
25
+ { [styles.notReachedTitle]: isDisabled }
26
+ );
27
+
28
+ return (
29
+ <div className={styles.orderReceivedCardContainer}>
30
+ <div className={orderReceivedCardClasses} ref={cardRef}>
31
+ <div className={styles.cardIcon}>
32
+ <IconSVG disabled={isDisabled} customDimensions name={icon} width={87}/>
33
+ </div>
34
+ <div data-testid='cardTitle' className={orderStatusTitleClasses}>{title}</div>
35
+ <div className={styles.orderStatusDesc}>{description}</div>
36
+ </div>
37
+ </div>
38
+ );
39
+ };
40
+
41
+ export default OrderStatusCard;
@@ -0,0 +1,63 @@
1
+ import React from 'react';
2
+ import { storiesOf } from '@storybook/react';
3
+
4
+ import OrderStatusSection from './OrderStatusSection';
5
+
6
+ const orderedCars = [
7
+ {
8
+ car: {
9
+ _id: '1234567890',
10
+ mainData: {
11
+ make: 'Volvo',
12
+ model: 'CX90',
13
+ subModel: 'sub model',
14
+ },
15
+ metaData: {
16
+ mainImageId: 'main image id'
17
+ }
18
+ },
19
+ buyingType: 'leasing',
20
+ selfPickup: true,
21
+ paybackPeriod: 24,
22
+ monthlyInstallment: 1000,
23
+ status: 'selector_status_preparation',
24
+ request: '010203',
25
+ registration: true,
26
+ currentSalesPrice: 20000
27
+ },
28
+ {
29
+ car: {
30
+ _id: '1234567890',
31
+ mainData: {
32
+ make: 'Volvo',
33
+ model: 'CX90',
34
+ subModel: 'sub model',
35
+ },
36
+ metaData: {
37
+ mainImageId: 'main image id'
38
+ }
39
+ },
40
+ buyingType: 'leasing',
41
+ selfPickup: false,
42
+ paybackPeriod: 24,
43
+ monthlyInstallment: 1000,
44
+ status: 'selector_status_preparation',
45
+ request: '010203',
46
+ registration: false,
47
+ currentSalesPrice: 20000
48
+ }
49
+ ];
50
+
51
+ const props = {
52
+ t: (phrase) => phrase,
53
+ redirectToCar: (id) => console.log(`redirect to car with id: ${id}`),
54
+ getSupportedImageFormat: (id, mainImageId, size) => 'https://images.autode-dev.de/carimage/28121b1a-398c-4e9c-9097-51be545817c5/RQ_mHNek5hIk/small-cached.webp',
55
+ isFetching: false,
56
+ withAdditionalInfo: false,
57
+ orderedCars
58
+ };
59
+
60
+ storiesOf('userDashboard', module)
61
+ .add('OrderStatusSection', () => (
62
+ <OrderStatusSection {...props} />
63
+ ));
@@ -0,0 +1,167 @@
1
+ @import '../../../../theme/mixins.styl'
2
+
3
+ .orderedCar:not(:first-child)
4
+ border-top: 1px solid rgba(76, 78, 100, 0.12)
5
+
6
+ .orderReceivedSection
7
+ display: grid
8
+ grid-template-areas: 'car cards'
9
+ +media-tablet-landscape-down()
10
+ grid-template-areas:
11
+ 'cards'\
12
+ 'car'
13
+
14
+
15
+ .orderStatus
16
+ font-weight: bold
17
+
18
+ .cardsSection
19
+ display: grid
20
+ grid-template-columns: repeat(5, auto)
21
+ box-sizing: border-box
22
+ padding: 12px
23
+ justify-content: space-between
24
+ grid-area: cards
25
+ +media-tablet-landscape-down()
26
+ overflow: scroll
27
+
28
+
29
+ .carCardWrapper
30
+ grid-area: car
31
+ width: 271px
32
+ cursor: pointer
33
+ border-right: 1px solid rgba(76, 78, 100, 0.12)
34
+ +media-tablet-landscape-down()
35
+ width: 100%
36
+ border-top: 1px solid rgba(76, 78, 100, 0.12)
37
+ border-right: none
38
+ max-width: none
39
+
40
+ .carCard
41
+ padding: 16px
42
+ display: grid
43
+ grid-template-areas:
44
+ 'marke'\
45
+ 'characteristics'\
46
+ 'carImage'\
47
+ 'requestId'\
48
+ 'paymentCar'
49
+
50
+ +media-tablet-landscape-down()
51
+ border-right: none
52
+ padding: 16px 20px 12px
53
+ grid-column-gap: 10px
54
+ max-width: 100%
55
+ justify-content: space-around
56
+ grid-template-areas:
57
+ 'marke carImage'\
58
+ 'characteristics carImage'\
59
+ 'requestId carImage'\
60
+ 'paymentCar paymentCar'
61
+
62
+ .carMarke
63
+ font-size: 20px;
64
+ line-height: 23px;
65
+ text-align: center;
66
+ letter-spacing: 0.15px;
67
+ font-weight: bold
68
+ color: rgba(76, 78, 100, 0.87);
69
+ grid-area: marke
70
+
71
+ .carCharacteristics
72
+ @extend .carMarke
73
+ font-size: 12px
74
+ line-height: 14px
75
+ grid-area: characteristics
76
+ max-width: 227px
77
+ letter-spacing: 0.15px
78
+ font-weight: bold
79
+ -webkit-line-clamp: 1
80
+ display: -webkit-box
81
+ -webkit-box-orient: vertical
82
+ overflow: hidden
83
+ height: fit-content
84
+ margin: 0 auto
85
+
86
+ .requestId
87
+ @extend .carCharacteristics
88
+ font-weight: normal
89
+ grid-area: requestId
90
+
91
+ .carImg
92
+ grid-area: carImage
93
+ width: 192px
94
+ margin: 0 auto
95
+ +media-tablet-landscape-down()
96
+ width: 117px
97
+ height: auto
98
+ img
99
+ width: 100%
100
+
101
+ .carPayment
102
+ font-size: 12px;
103
+ line-height: 20px;
104
+ text-align: center;
105
+ letter-spacing: 0.15px;
106
+ color: rgba(76, 78, 100, 0.87);
107
+ grid-area: paymentCar
108
+ +media-tablet-landscape-down()
109
+ padding: 16px 5px 0
110
+ border-top: 1px solid rgba(76, 78, 100, 0.12)
111
+ font-size: 14px
112
+
113
+ .react-slider-container
114
+ width: 100%
115
+
116
+ // .sliderContainer
117
+ // max-width: 1090px;
118
+ // +media-tablet-landscape-down()
119
+ // width: calc(100vw - 32px)
120
+ // box-sizing: border-box
121
+ // :global
122
+ // .slick-slider
123
+ // overflow: hidden
124
+ // +media-tablet-landscape-down()
125
+ // padding 0;
126
+ // .slick-arrow,
127
+ // .slick-arrow:focus,
128
+ // .slick-arrow:hover
129
+ // display: inline-block
130
+ // width: 25px
131
+ // height: 50px
132
+ // z-index: 1
133
+ // transition: all 0.2s ease-in-out
134
+ // .slick-arrow::before
135
+ // display: none
136
+ // .click-arrow::before:hover
137
+ // background-color: black
138
+
139
+ // .slick-arrow::after
140
+ // position: absolute
141
+ // content: ''
142
+ // display: inline-block
143
+ // width: inherit
144
+ // height: inherit
145
+ // top: 50%
146
+ // transform: translateY(-50%)
147
+ // transform-origin: top center
148
+ // background-image: url('../../../../../../media/images/slider-arrow-new.svg')
149
+ // background-size: cover
150
+
151
+ // .slick-next::after
152
+ // left: 0
153
+
154
+ // .slick-prev::after
155
+ // transform: rotate(180deg) translateY(-50%)
156
+ // right: 0
157
+
158
+ // .slick-prev
159
+ // left: 5px
160
+ // top: 75%
161
+
162
+ // .slick-next
163
+ // right: 5px
164
+ // top: 75%
165
+
166
+ .skeletonBlock
167
+ height: 330px
@@ -0,0 +1,128 @@
1
+ import React from 'react';
2
+
3
+ import DashboardSection from '../../../containers/DasboardSection/DashboardSection';
4
+ // import AdditionalOrderInfo from './AdditionalOrderInfo';
5
+ import OrderStatusCar from './OrderStatusCar';
6
+ import styles from './OrderStatusSection.styl';
7
+ // import { history } from '../../../../../AppRouter';
8
+ import { Skeleton } from '@mui/material';
9
+ import i18next from 'i18next';
10
+
11
+ interface IOrderStatusSection {
12
+ redirectToCar: (id: string) => void;
13
+ getSupportedImageFormat: (id: string, mainImageId: string, size: 'small' | 'medium' | 'large') => string;
14
+ t: i18next.TFunction;
15
+ isFetching: boolean;
16
+ withAdditionalInfo?: boolean; // for using on /account/my-order.
17
+ orderedCars: any[]; // TODO: create interface for orderedCars, when the object is formatted by the backend
18
+ }
19
+
20
+ const OrderStatusSection = ({
21
+ getSupportedImageFormat,
22
+ t,
23
+ orderedCars,
24
+ isFetching,
25
+ withAdditionalInfo = false,
26
+ redirectToCar
27
+ }: IOrderStatusSection) => {
28
+ const onDetailsClick = (carId: string) => {
29
+ redirectToCar(carId);
30
+ };
31
+
32
+ const renderRequestedCars = () => {
33
+ return (
34
+ <>
35
+ {!!orderedCars && orderedCars.map((orderedCar, index) => {
36
+ const { car: { _id } } = orderedCar;
37
+ const { car: { mainData: { make, model, subModel } } } = orderedCar;
38
+ const { car: { metaData: { mainImageId } } } = orderedCar;
39
+ const {
40
+ buyingType,
41
+ selfPickup,
42
+ paybackPeriod,
43
+ monthlyInstallment,
44
+ status,
45
+ request,
46
+ registration,
47
+ currentSalesPrice
48
+ } = orderedCar;
49
+
50
+ // ---- data for testing additionalInfo ----
51
+
52
+ // const additionalOrderData = {
53
+ // addressData: [
54
+ // { label: 'Billing address:', value: 'Hannes Käther, Wittenberger Str. 81, 04129 Leipzig' },
55
+ // { label: 'Vehicle delivery:', value: 'Hannes Käther, Wittenberger Str. 81, 04129 Leipzig' }
56
+ // ],
57
+ // carPriceData: [
58
+ // { label: 'Car price', value: '22.799,00 €' },
59
+ // { label: 'Preparation cost', value: '799,00 €' },
60
+ // { label: 'vehicle registration', value: '399,00 €' },
61
+ // { label: 'Silver Guarantee Pack (2 years)', value: '1.099,00 €' },
62
+ // { label: 'license plates', value: '140,66 €' },
63
+ // { label: 'Delivery', value: '799,36 €' }
64
+ // ],
65
+ // financingData: [
66
+ // { label: 'Leasing rate', value: '€194.00 per month' },
67
+ // { label: 'Running time (months)', value: '72 months' },
68
+ // { label: 'Deposit', value: '1.000,99 €' }
69
+ // ],
70
+ // overallRate: {
71
+ // label: 'Your overall rate',
72
+ // value: 599
73
+ // }
74
+ // };
75
+
76
+ // const additionalOrderInfoProps = {
77
+ // t,
78
+ // additionalOrderData
79
+ // };
80
+
81
+ const imageUrl = getSupportedImageFormat(_id, mainImageId, 'small');
82
+
83
+ const orderStatusCarProps = {
84
+ make,
85
+ model,
86
+ subModel,
87
+ buyingType,
88
+ imageUrl,
89
+ selfPickup,
90
+ paybackPeriod,
91
+ monthlyInstallment,
92
+ status,
93
+ t,
94
+ request,
95
+ registration,
96
+ currentSalesPrice,
97
+ onClick: () => onDetailsClick(_id)
98
+ };
99
+
100
+ const title = <span>
101
+ {t('orderStatus.title')}:&nbsp;
102
+ <span className={styles.orderStatus}>{t(`orderStatus.${status}`)}</span>
103
+ </span>;
104
+
105
+ return (
106
+ <DashboardSection key={index} title={title}>
107
+ <OrderStatusCar { ...orderStatusCarProps } />
108
+ {/* {withAdditionalInfo ? <AdditionalOrderInfo { ...additionalOrderInfoProps } /> : null} */}
109
+ </DashboardSection>
110
+ );
111
+ })}
112
+ </>
113
+ );
114
+ };
115
+
116
+ return (
117
+ <>
118
+ {isFetching ?
119
+ <div className={styles.skeletonBlock}>
120
+ <Skeleton animation='wave' variant='rectangular' width='100%' />
121
+ </div>
122
+ : renderRequestedCars()
123
+ }
124
+ </>
125
+ );
126
+ };
127
+
128
+ export default OrderStatusSection;
@@ -143,7 +143,6 @@ const VehiclePrice: React.FC<IVehiclePriceSectionProps> = (props: IVehiclePriceS
143
143
  vehicleComponentName === 'landing' ||
144
144
  vehicleComponentName === 'main' ? 'outlined' : 'contained';
145
145
 
146
-
147
146
  const priceItemsGlobal = [
148
147
  {
149
148
  perMonthOld: oldMonthlyInstallment,
@@ -280,4 +279,4 @@ const VehiclePrice: React.FC<IVehiclePriceSectionProps> = (props: IVehiclePriceS
280
279
  );
281
280
  };
282
281
 
283
- export default VehiclePrice;
282
+ export default VehiclePrice;
@@ -276,7 +276,7 @@ const VehicleSmallCard: FunctionComponent<IVehicleSmallCardProps> = (props) => {
276
276
  vehicleComponentName === 'recently';
277
277
  return (
278
278
  <section className={wrapperClassName} onClick={onContainerClick} id={id}>
279
- <>
279
+ <>
280
280
  {createElement(linkTag, {
281
281
  children: <VehicleTitle {...favoriteProps} />,
282
282
  ...routeObj,
@@ -7,7 +7,7 @@ type TIconSVG = {
7
7
  customDimensions?: boolean;
8
8
  };
9
9
 
10
- const IconSVG: React.FC<TIconSVG> = ({ name, customDimensions, ...props }: TIconSVG) => {
10
+ const IconSVG: React.FC<TIconSVG> = ({ name, isWarrantyActive, customDimensions, ...props }: TIconSVG) => {
11
11
  if (!name) return null;
12
12
 
13
13
  const Component: any = components[name.toString()];
@@ -45,9 +45,12 @@ const MaterialField: React.FC<IVehicleModalProps> = ({
45
45
  const [showPassword, setShowPassword] = React.useState(false);
46
46
  const [enteredValue, setEnteredValue] = useState(value);
47
47
 
48
- useEffect(() => {
49
- setEnteredValue(value);
50
- }, [value])
48
+ useEffect(
49
+ () => {
50
+ setEnteredValue(value);
51
+ },
52
+ [value]
53
+ );
51
54
 
52
55
  const onHandleChange = (event?: React.ChangeEvent<HTMLInputElement | HTMLTextAreaElement>) => {
53
56
  const value = event.currentTarget.value;
@@ -11,7 +11,6 @@ import { preloadNearbyImages } from '../../../framework/utils/CommonUtils';
11
11
  import { IVehicleSliderForSRLProps } from '../../../framework/types/types';
12
12
  import styles from './VehicleSlider.styl';
13
13
 
14
-
15
14
  const SlickButtonFix: React.FC = ({ currentSlide, slideCount, children, ...props }: any) => (
16
15
  <div {...props} tabIndex={-1}>{children}</div>
17
16
  );
@@ -32,8 +31,8 @@ const VehicleSliderForSRL: React.FC<IVehicleSliderForSRLProps> = ({
32
31
  CircularProgressbar,
33
32
  onSlideChange
34
33
  }: IVehicleSliderForSRLProps) => {
35
- const [ noImagesLoaded, setNoImagesLoaded ] = React.useState<boolean>(false);
36
- const [ activeSlide, setActiveSlide ] = React.useState<number>(0);
34
+ const [noImagesLoaded, setNoImagesLoaded] = React.useState<boolean>(false);
35
+ const [activeSlide, setActiveSlide] = React.useState<number>(0);
37
36
 
38
37
  const beforeChange = () => {
39
38
 
@@ -163,6 +162,6 @@ VehicleSliderForSRL.defaultProps = {
163
162
  typeAlternative: '',
164
163
  images: [],
165
164
  getCarImagesData: () => null
166
- }
165
+ };
167
166
 
168
167
  export default VehicleSliderForSRL;
@@ -52,7 +52,7 @@ const withStats = (WrappedComponent: any) => ({
52
52
  price: { historyPriceDifference = 0, historyPriceDifferencePerCent = 0 },
53
53
  ...props
54
54
  }: IStatsWrapperProps) => {
55
- const [ activeSlide, setActiveSlide ] = React.useState<number>(0);
55
+ const [activeSlide, setActiveSlide] = React.useState<number>(0);
56
56
 
57
57
  const MIN_PERCENT = 5;
58
58
  const MIN_PRICE_DIFFERENCE = 500;
@@ -160,7 +160,7 @@ const withStats = (WrappedComponent: any) => ({
160
160
  imagesCount,
161
161
  classWrapPrice,
162
162
  ...props
163
- }
163
+ };
164
164
 
165
165
  return (
166
166
  <div className={styles.wrapper}>
@@ -176,4 +176,4 @@ const withStats = (WrappedComponent: any) => ({
176
176
  );
177
177
  };
178
178
 
179
- export default withStats;
179
+ export default withStats;
@@ -0,0 +1,15 @@
1
+ .dashboardSectionWrapper
2
+ border: 1px solid rgba(76, 78, 100, 0.12)
3
+ border-radius: 8px
4
+ background-color: #fff
5
+ box-sizing: border-box
6
+
7
+ .title
8
+ border-bottom: 1px solid rgba(76, 78, 100, 0.12)
9
+ padding: 16px 16px 8px
10
+ font-size: 20px
11
+ line-height: 32px
12
+ letter-spacing: 0.15px
13
+ color: rgba(76, 78, 100, 0.87)
14
+ display: flex;
15
+ justify-content: space-between;
@@ -0,0 +1,23 @@
1
+ import React from 'react';
2
+ import styles from './DashboardSection.styl';
3
+
4
+ interface IRecentlySectionProps {
5
+ className?: string;
6
+ title: any;
7
+ children: any;
8
+ link?: any;
9
+ }
10
+
11
+ const DashboardSection = ({ children, title, className, link }: IRecentlySectionProps) => {
12
+ return (
13
+ <div className={styles.dashboardSectionWrapper}>
14
+ <div className={styles.title}>
15
+ <span>{title}</span>
16
+ {link}
17
+ </div>
18
+ <div className={className}>{children}</div>
19
+ </div>
20
+ );
21
+ };
22
+
23
+ export default DashboardSection;