@bytebrand/fe-ui-core 4.2.52 → 4.2.54
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/__tests__/components/UserDasboardPage/sections/OrderStatusSection/OrderStatusCar.test.tsx +58 -0
- package/__tests__/components/UserDasboardPage/sections/OrderStatusSection/OrderStatusCard.test.tsx +78 -0
- package/__tests__/components/_common/{Badge.test.tsx → Badge/Badge.test.tsx} +1 -1
- package/jest.config.js +5 -4
- package/package.json +5 -2
- package/source/components/SearchPage/Filters/MakeModel/MakeModel.tsx +1 -1
- package/source/components/UserDashboardPage/sections/OrderStatusSection/AdditionalOrderInfo.styl +73 -0
- package/source/components/UserDashboardPage/sections/OrderStatusSection/AdditionalOrderInfo.tsx +89 -0
- package/source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusCar.tsx +128 -0
- package/source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusCard.styl +54 -0
- package/source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusCard.tsx +41 -0
- package/source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusSection.story.js +95 -0
- package/source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusSection.styl +167 -0
- package/source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusSection.tsx +128 -0
- package/source/components/VehicleSmallCard/VehicleData/VehiclePrice/VehiclePrice.tsx +1 -2
- package/source/components/VehicleSmallCard/VehicleSmallCard.tsx +1 -1
- package/source/components/_common/MaterialField/MaterialField.tsx +6 -3
- package/source/components/_common/VehicleSlider/VehicleSliderForSRL.tsx +3 -4
- package/source/components/_common/withStats/withStats.tsx +3 -3
- package/source/components/containers/DasboardSection/DashboardSection.styl +15 -0
- package/source/components/containers/DasboardSection/DashboardSection.tsx +23 -0
- package/source/framework/utils/CommonUtils.ts +9 -0
package/__tests__/components/UserDasboardPage/sections/OrderStatusSection/OrderStatusCar.test.tsx
ADDED
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render, fireEvent } from '@testing-library/react'
|
|
3
|
+
import OrderStatusCar from '../../../../../source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusCar';
|
|
4
|
+
|
|
5
|
+
const t = (phrase: string | string[], options: object) => {
|
|
6
|
+
if (options) {
|
|
7
|
+
const value = Object.values(options).map((option) => option)
|
|
8
|
+
return `${phrase} ${value}`;
|
|
9
|
+
}
|
|
10
|
+
return phrase;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
const mockProps = {
|
|
14
|
+
t,
|
|
15
|
+
make: 'Test Make',
|
|
16
|
+
model: 'Test Model',
|
|
17
|
+
subModel: 'test car',
|
|
18
|
+
buyingType: 'buy',
|
|
19
|
+
imageUrl: 'https://images.autode-dev.de/carimage/28121b1a-398c-4e9c-9097-51be545817c5/RQ_mHNek5hIk/small-cached.webp',
|
|
20
|
+
selfPickup: false,
|
|
21
|
+
paybackPeriod: 12,
|
|
22
|
+
monthlyInstallment: 2000,
|
|
23
|
+
status: 'selector_status_order_received',
|
|
24
|
+
request: '1234abcd',
|
|
25
|
+
registration: false,
|
|
26
|
+
currentSalesPrice: 30000,
|
|
27
|
+
onClick: jest.fn()
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
describe('OrderStatusCar', () => {
|
|
31
|
+
it('renders OrderStatusCar component without error', () => {
|
|
32
|
+
const { container } = render(<OrderStatusCar {...mockProps} />);
|
|
33
|
+
expect(container).toBeInTheDocument();
|
|
34
|
+
});
|
|
35
|
+
|
|
36
|
+
it('should display correct car make and model', () => {
|
|
37
|
+
const { getByText } = render(<OrderStatusCar {...mockProps} />);
|
|
38
|
+
expect(getByText(`${mockProps.make} ${mockProps.model}`)).toBeInTheDocument();
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
it('should display correct car characteristics', () => {
|
|
42
|
+
const { getByText } = render(<OrderStatusCar {...mockProps} />);
|
|
43
|
+
expect(getByText(mockProps.subModel)).toBeInTheDocument();
|
|
44
|
+
});
|
|
45
|
+
|
|
46
|
+
it('should display correct car image', () => {
|
|
47
|
+
const { getByTestId } = render(<OrderStatusCar {...mockProps}/>);
|
|
48
|
+
const carImage = getByTestId('car-image')
|
|
49
|
+
expect(carImage).toHaveAttribute('src', mockProps.imageUrl);
|
|
50
|
+
});
|
|
51
|
+
|
|
52
|
+
it('should call onClick function when user clicks on the car card', () => {
|
|
53
|
+
const { getByTestId } = render(<OrderStatusCar {...mockProps} />);
|
|
54
|
+
const carCard = getByTestId('car-card');
|
|
55
|
+
fireEvent.click(carCard);
|
|
56
|
+
expect(mockProps.onClick).toHaveBeenCalled();
|
|
57
|
+
});
|
|
58
|
+
});
|
package/__tests__/components/UserDasboardPage/sections/OrderStatusSection/OrderStatusCard.test.tsx
ADDED
|
@@ -0,0 +1,78 @@
|
|
|
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('render container without errors', () => {
|
|
10
|
+
const { container } = render(
|
|
11
|
+
<OrderStatusCard
|
|
12
|
+
icon={icon}
|
|
13
|
+
title={title}
|
|
14
|
+
description={description}
|
|
15
|
+
/>
|
|
16
|
+
);
|
|
17
|
+
expect(container).toBeInTheDocument();
|
|
18
|
+
});
|
|
19
|
+
|
|
20
|
+
it('renders a card with title, description, and icon', () => {
|
|
21
|
+
const { getByText, container, debug } = render(
|
|
22
|
+
<OrderStatusCard
|
|
23
|
+
icon={icon}
|
|
24
|
+
title={title}
|
|
25
|
+
description={description}
|
|
26
|
+
/>
|
|
27
|
+
);
|
|
28
|
+
debug();
|
|
29
|
+
const cardTitle = getByText(title);
|
|
30
|
+
expect(cardTitle).toBeInTheDocument();
|
|
31
|
+
const cardDescription = getByText(description);
|
|
32
|
+
expect(cardDescription).toBeInTheDocument();
|
|
33
|
+
const svgElement = container.querySelector('svg');
|
|
34
|
+
expect(svgElement).toBeInTheDocument();
|
|
35
|
+
});
|
|
36
|
+
|
|
37
|
+
it('adds "notReachedTitle" class for title when "isDisabled" prop is set', () => {
|
|
38
|
+
const { getByTestId, debug } = render(
|
|
39
|
+
<OrderStatusCard
|
|
40
|
+
icon={icon}
|
|
41
|
+
title={title}
|
|
42
|
+
description={description}
|
|
43
|
+
isDisabled={true}
|
|
44
|
+
/>
|
|
45
|
+
);
|
|
46
|
+
debug();
|
|
47
|
+
const cardTitle = getByTestId('cardTitle');
|
|
48
|
+
expect(cardTitle).toHaveClass('notReachedTitle');
|
|
49
|
+
});
|
|
50
|
+
|
|
51
|
+
it('adds "isDoneTitle" class for title when "isDone" prop is set', () => {
|
|
52
|
+
const { getByTestId, debug } = render(
|
|
53
|
+
<OrderStatusCard
|
|
54
|
+
icon={icon}
|
|
55
|
+
title={title}
|
|
56
|
+
description={description}
|
|
57
|
+
isDone={true}
|
|
58
|
+
/>
|
|
59
|
+
);
|
|
60
|
+
debug();
|
|
61
|
+
const cardTitle = getByTestId('cardTitle');
|
|
62
|
+
expect(cardTitle).toHaveClass('isDoneTitle');
|
|
63
|
+
});
|
|
64
|
+
|
|
65
|
+
it('adds "cardInProgress" class for card when "isActive" prop is set', () => {
|
|
66
|
+
const { getByTestId, debug } = render(
|
|
67
|
+
<OrderStatusCard
|
|
68
|
+
icon={icon}
|
|
69
|
+
title={title}
|
|
70
|
+
description={description}
|
|
71
|
+
isActive={true}
|
|
72
|
+
/>
|
|
73
|
+
);
|
|
74
|
+
debug();
|
|
75
|
+
const orderStatusCard = getByTestId('orderStatusCard');
|
|
76
|
+
expect(orderStatusCard).toHaveClass('cardInProgress');
|
|
77
|
+
});
|
|
78
|
+
});
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React from 'react';
|
|
2
2
|
import { render } from '@testing-library/react';
|
|
3
|
-
import Badge from '
|
|
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|
|
|
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|
|
|
27
|
+
"^.+.(css|less|sass|scss|png|jpg|ttf|woff|woff2)$": "jest-transform-stub",
|
|
27
28
|
"^.+\\.svg$": "jest-svg-transformer",
|
|
28
|
-
|
|
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.
|
|
3
|
+
"version": "4.2.54",
|
|
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
|
);
|
package/source/components/UserDashboardPage/sections/OrderStatusSection/AdditionalOrderInfo.styl
ADDED
|
@@ -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
|
package/source/components/UserDashboardPage/sections/OrderStatusSection/AdditionalOrderInfo.tsx
ADDED
|
@@ -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,128 @@
|
|
|
1
|
+
import React, { useRef, useEffect, useState } from 'react';
|
|
2
|
+
import styles from './OrderStatusSection.styl';
|
|
3
|
+
import OrderStatusCard from './OrderStatusCard';
|
|
4
|
+
import Image from '../../../_common/Image/Image';
|
|
5
|
+
import { getFormattedPrice } from '../../../../framework/utils/CommonUtils';
|
|
6
|
+
|
|
7
|
+
interface TFunction {
|
|
8
|
+
<T = string>(key: string, options?: object): T;
|
|
9
|
+
<T = string>(keys: string[], options?: object): T;
|
|
10
|
+
}
|
|
11
|
+
interface IOrderStatusCar {
|
|
12
|
+
make?: string;
|
|
13
|
+
model?: string;
|
|
14
|
+
subModel?: string;
|
|
15
|
+
buyingType?: string;
|
|
16
|
+
imageUrl?: string;
|
|
17
|
+
selfPickup?: boolean;
|
|
18
|
+
paybackPeriod?: number;
|
|
19
|
+
monthlyInstallment?: number;
|
|
20
|
+
status?: string;
|
|
21
|
+
t: TFunction;
|
|
22
|
+
request: string;
|
|
23
|
+
registration: boolean;
|
|
24
|
+
currentSalesPrice: number;
|
|
25
|
+
onClick: () => void;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
const OrderStatusCar = ({
|
|
29
|
+
make,
|
|
30
|
+
model,
|
|
31
|
+
subModel,
|
|
32
|
+
buyingType,
|
|
33
|
+
selfPickup,
|
|
34
|
+
paybackPeriod,
|
|
35
|
+
monthlyInstallment,
|
|
36
|
+
imageUrl,
|
|
37
|
+
status,
|
|
38
|
+
t,
|
|
39
|
+
request,
|
|
40
|
+
registration,
|
|
41
|
+
currentSalesPrice,
|
|
42
|
+
onClick
|
|
43
|
+
}: IOrderStatusCar) => {
|
|
44
|
+
const ref = useRef(null);
|
|
45
|
+
const [activeStep, setActiveStep] = useState(0); // 0 - when we have no active steps
|
|
46
|
+
|
|
47
|
+
const cardItems = [
|
|
48
|
+
{ icon: 'orderReceivedDashboard', selector: 'selector_status_order_received' },
|
|
49
|
+
{ icon: 'preparaionDashboard', selector: 'selector_status_preparation' },
|
|
50
|
+
{ icon: 'registrationDashboard', selector: 'selector_status_registration' },
|
|
51
|
+
selfPickup ? { icon: 'pickupDashboard', selector: 'selector_status_pick_up' }
|
|
52
|
+
: { icon: 'deliveryDashboard', selector: 'selector_status_delivery' },
|
|
53
|
+
{ icon: 'handingOverDashboard', selector: 'selector_status_handing_over' }
|
|
54
|
+
];
|
|
55
|
+
|
|
56
|
+
useEffect(
|
|
57
|
+
() => {
|
|
58
|
+
cardItems.map((step, index) => {
|
|
59
|
+
const { selector } = step;
|
|
60
|
+
if (selector === status) {
|
|
61
|
+
setActiveStep(index + 1);
|
|
62
|
+
}
|
|
63
|
+
});
|
|
64
|
+
// if (!!ref && !!ref.current) { TODO: fix scroll for active element for mobile
|
|
65
|
+
// ref.current.scrollBy({
|
|
66
|
+
// top: 0,
|
|
67
|
+
// left: 156 * activeStep,
|
|
68
|
+
// behavior: 'smooth'
|
|
69
|
+
// });
|
|
70
|
+
// }
|
|
71
|
+
},
|
|
72
|
+
[]
|
|
73
|
+
);
|
|
74
|
+
|
|
75
|
+
return (
|
|
76
|
+
<div className={styles.orderedCar}>
|
|
77
|
+
<div className={styles.orderReceivedSection}>
|
|
78
|
+
<div className={styles.carCardWrapper} data-testid='car-card' onClick={onClick}>
|
|
79
|
+
<div className={styles.carCard}>
|
|
80
|
+
<div className={styles.carMarke}>
|
|
81
|
+
{make} {model}
|
|
82
|
+
</div>
|
|
83
|
+
<div className={styles.carCharacteristics}>
|
|
84
|
+
{subModel}
|
|
85
|
+
</div>
|
|
86
|
+
<div className={styles.carImg}>
|
|
87
|
+
{/* <Image className={styles.carImg} width='100%' ratioW={4} ratioH={3} src={imageUrl} /> */}
|
|
88
|
+
<img data-testid='car-image' src={imageUrl}/>
|
|
89
|
+
</div>
|
|
90
|
+
<div className={styles.requestId}>{request}</div>
|
|
91
|
+
<div className={styles.carPayment} >
|
|
92
|
+
{t(`buyingType.${buyingType}`)},
|
|
93
|
+
{buyingType !== 'buy' && `${t('paybackPeriod', { paybackPeriod })},`}
|
|
94
|
+
{buyingType === 'buy' ?
|
|
95
|
+
t('currentSalesPrice', { currentSalesPrice: getFormattedPrice(currentSalesPrice) })
|
|
96
|
+
: t('monthlyInstallment', { monthlyInstallment: getFormattedPrice(monthlyInstallment, '$,.2f') })
|
|
97
|
+
}
|
|
98
|
+
</div>
|
|
99
|
+
</div>
|
|
100
|
+
</div>
|
|
101
|
+
<div className={styles.cardsSection}>
|
|
102
|
+
{cardItems.map((card, index) => {
|
|
103
|
+
const { icon, selector } = card;
|
|
104
|
+
|
|
105
|
+
const statusDescription = !registration && index === 2 ?
|
|
106
|
+
t('orderStatus.independentRegistration') :
|
|
107
|
+
t(`orderStatus.${selector}_desc`);
|
|
108
|
+
|
|
109
|
+
return (
|
|
110
|
+
<OrderStatusCard
|
|
111
|
+
cardRef={selector === status ? ref : null}
|
|
112
|
+
title={t(`orderStatus.${selector}`)}
|
|
113
|
+
description={statusDescription}
|
|
114
|
+
icon={icon}
|
|
115
|
+
key={index}
|
|
116
|
+
isActive={index + 1 === activeStep}
|
|
117
|
+
isDisabled={index + 1 > activeStep}
|
|
118
|
+
isDone={index + 1 < activeStep}
|
|
119
|
+
/>
|
|
120
|
+
);
|
|
121
|
+
})}
|
|
122
|
+
</div>
|
|
123
|
+
</div>
|
|
124
|
+
</div>
|
|
125
|
+
);
|
|
126
|
+
};
|
|
127
|
+
|
|
128
|
+
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 data-testid='orderStatusCard' 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;
|
package/source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusSection.story.js
ADDED
|
@@ -0,0 +1,95 @@
|
|
|
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_registration',
|
|
45
|
+
request: '010203',
|
|
46
|
+
registration: false,
|
|
47
|
+
currentSalesPrice: 20000
|
|
48
|
+
}
|
|
49
|
+
];
|
|
50
|
+
|
|
51
|
+
const translates = {
|
|
52
|
+
'orderStatus.title': 'Order status',
|
|
53
|
+
'orderStatus.selector_status_order_received': 'order received',
|
|
54
|
+
'orderStatus.selector_status_preparation': 'preparation',
|
|
55
|
+
'orderStatus.selector_status_registration': 'registration',
|
|
56
|
+
'orderStatus.selector_status_pick_up': 'pickup',
|
|
57
|
+
'orderStatus.selector_status_handing_over': 'handing over',
|
|
58
|
+
'orderStatus.selector_status_delivery': 'delivery',
|
|
59
|
+
'orderStatus.independentRegistration': 'independent registration',
|
|
60
|
+
'orderStatus.selector_status_order_received_desc': 'order received description',
|
|
61
|
+
'orderStatus.selector_status_preparation_desc': 'preparation description',
|
|
62
|
+
'orderStatus.selector_status_registration_desc': 'registration description',
|
|
63
|
+
'orderStatus.selector_status_pick_up_desc': 'pickup description',
|
|
64
|
+
'orderStatus.selector_status_handing_over_desc': 'handing over description',
|
|
65
|
+
'orderStatus.selector_status_delivery_desc': 'delivery description',
|
|
66
|
+
'buyingType.buy': 'buy',
|
|
67
|
+
'buyingType.leasing': 'leasing',
|
|
68
|
+
'buyingType.financing': 'financing',
|
|
69
|
+
'paybackPeriod': 'payback period',
|
|
70
|
+
'currentSalesPrice': 'current sales price',
|
|
71
|
+
'monthlyInstallment': 'monthly installment'
|
|
72
|
+
}
|
|
73
|
+
|
|
74
|
+
const t = (phrase, options) => {
|
|
75
|
+
if (options) {
|
|
76
|
+
console.log('qqqq options ====', options);
|
|
77
|
+
const value = Object.values(options).map((option) => option)
|
|
78
|
+
return `${translates[phrase]} ${value}`;
|
|
79
|
+
}
|
|
80
|
+
return translates[phrase];
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
const props = {
|
|
84
|
+
t,
|
|
85
|
+
redirectToCar: (id) => console.log(`redirect to car with id: ${id}`),
|
|
86
|
+
getSupportedImageFormat: (id, mainImageId, size) => 'https://images.autode-dev.de/carimage/28121b1a-398c-4e9c-9097-51be545817c5/RQ_mHNek5hIk/small-cached.webp',
|
|
87
|
+
isFetching: false,
|
|
88
|
+
withAdditionalInfo: false,
|
|
89
|
+
orderedCars
|
|
90
|
+
};
|
|
91
|
+
|
|
92
|
+
storiesOf('userDashboard', module)
|
|
93
|
+
.add('OrderStatusSection', () => (
|
|
94
|
+
<OrderStatusSection {...props} />
|
|
95
|
+
));
|
package/source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusSection.styl
ADDED
|
@@ -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
|
package/source/components/UserDashboardPage/sections/OrderStatusSection/OrderStatusSection.tsx
ADDED
|
@@ -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')}:
|
|
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,
|
|
@@ -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
|
-
|
|
50
|
-
|
|
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 [
|
|
36
|
-
const [
|
|
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 [
|
|
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;
|
|
@@ -14,6 +14,15 @@ import { SearchPage as SearchPageTranslate } from '../../locales/data';
|
|
|
14
14
|
|
|
15
15
|
const PRICE_DEFAULT = DROP_DOWN_GROUP[PRICE].defaultValue;
|
|
16
16
|
|
|
17
|
+
declare global {
|
|
18
|
+
interface Window {
|
|
19
|
+
grantHotjarCookieConsent?: () => void;
|
|
20
|
+
grantCookieConsent?: (list: string[]) => void;
|
|
21
|
+
allowGoogle?: () => void;
|
|
22
|
+
fbq?: (option1: string, option2: string) => void;
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
|
|
17
26
|
export const formatMileage = (millage: number | string) => {
|
|
18
27
|
return millage.toLocaleString('en-US').replace(/,/g, '.');
|
|
19
28
|
};
|