@bytebrand/fe-ui-core 4.2.142 → 4.2.144
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/FavoriteSection/FavoriteSection.test.tsx +373 -0
- package/__tests__/utils/CommonUtils/getOfferSliders.test.ts +4 -2
- package/package.json +2 -1
- package/source/components/UserDashboardPage/sections/FavoriteSection/FavoriteSection.styl +22 -0
- package/source/components/UserDashboardPage/sections/FavoriteSection/FavoriteSection.tsx +112 -0
- package/source/components/UserDashboardPage/sections/RequestedCarsSection/RequestedCarsSection.tsx +2 -1
- package/source/components/VehicleSmallCard/VehicleData/VehiclePrice/VehiclePrice.tsx +1 -1
- package/source/components/containers/SearchPage/FiltersContainer/FiltersContainer.tsx +38 -33
package/__tests__/components/UserDasboardPage/sections/FavoriteSection/FavoriteSection.test.tsx
ADDED
|
@@ -0,0 +1,373 @@
|
|
|
1
|
+
import React from 'react';
|
|
2
|
+
import { render } from '@testing-library/react';
|
|
3
|
+
import FavoriteSection from '../../../../../source/components/UserDashboardPage/sections/FavoriteSection/FavoriteSection';
|
|
4
|
+
import { observable } from 'mobx';
|
|
5
|
+
import qs from 'qs';
|
|
6
|
+
|
|
7
|
+
const t = (phrase: string | string[], options: object) => {
|
|
8
|
+
if (options) {
|
|
9
|
+
const value = Object.values(options).map((option) => option);
|
|
10
|
+
return `${phrase} ${value}`;
|
|
11
|
+
}
|
|
12
|
+
return phrase;
|
|
13
|
+
};
|
|
14
|
+
|
|
15
|
+
interface IWithRouter {
|
|
16
|
+
children?: JSX.Element;
|
|
17
|
+
link?: string;
|
|
18
|
+
}
|
|
19
|
+
const LinkRouter = ({ children, link }: IWithRouter) => {
|
|
20
|
+
return (
|
|
21
|
+
<a href={link} >
|
|
22
|
+
{children}
|
|
23
|
+
</a>
|
|
24
|
+
);
|
|
25
|
+
};
|
|
26
|
+
const favoriteCars = [
|
|
27
|
+
{
|
|
28
|
+
parkedFor: 'N/A',
|
|
29
|
+
id: 'c4c9141a-5e4c-4d75-9d0f-c2f1b8f31241',
|
|
30
|
+
mainImageId: ' ',
|
|
31
|
+
imagesCount: ' ',
|
|
32
|
+
hasInteriorExteriorPhoto: ' ',
|
|
33
|
+
title: {
|
|
34
|
+
make: 'Volkswagen',
|
|
35
|
+
model: 'Polo',
|
|
36
|
+
subModel: '1.0 TSI Style',
|
|
37
|
+
option: '',
|
|
38
|
+
to: ''
|
|
39
|
+
},
|
|
40
|
+
showNewLabel: false,
|
|
41
|
+
info: {
|
|
42
|
+
regDate: ' ',
|
|
43
|
+
mileage: 0,
|
|
44
|
+
gearbox: 'selector_gearbox_manualShift',
|
|
45
|
+
numberOfPreviousOwners: 0,
|
|
46
|
+
usageType: 'selector_unknown',
|
|
47
|
+
condition: 'selector_condition_new',
|
|
48
|
+
damaged: false,
|
|
49
|
+
driveType: 'selector_driveType_frontWheelDrive'
|
|
50
|
+
},
|
|
51
|
+
location: {
|
|
52
|
+
city: 't',
|
|
53
|
+
street: 't',
|
|
54
|
+
zipCode: 12345
|
|
55
|
+
},
|
|
56
|
+
consumption: {
|
|
57
|
+
fuel: 'selector_fuel_petrol',
|
|
58
|
+
consumptionCombined: 5.2,
|
|
59
|
+
consumptionPowerCombined: ' '
|
|
60
|
+
},
|
|
61
|
+
engineData: {
|
|
62
|
+
powerKW: 70,
|
|
63
|
+
powerPS: 70
|
|
64
|
+
},
|
|
65
|
+
environmentEmissions: {
|
|
66
|
+
co2: 118
|
|
67
|
+
},
|
|
68
|
+
offer: {
|
|
69
|
+
offerId: ' ',
|
|
70
|
+
autoDeOfferId: ' ',
|
|
71
|
+
offerFrom: 'selector_unknown',
|
|
72
|
+
offerSource: ' ',
|
|
73
|
+
offerAvailability: 'selector_unknown',
|
|
74
|
+
offerDescription: '',
|
|
75
|
+
deliveryDate: 1698969600,
|
|
76
|
+
deliveryPeriod: 'selector_deliveryPeriod_days270',
|
|
77
|
+
dealerHomepage: ' ',
|
|
78
|
+
closedDomain: ' ',
|
|
79
|
+
export: ' ',
|
|
80
|
+
commercial: ' ',
|
|
81
|
+
warranty: false,
|
|
82
|
+
rentingPossible: ' ',
|
|
83
|
+
newHuAu: true,
|
|
84
|
+
internalNumber: '118_92436S/3243',
|
|
85
|
+
availabilityMode: 'selector_availabilityMode_fromDate',
|
|
86
|
+
mobileDeOfferId: ' ',
|
|
87
|
+
as24DeOfferId: ' ',
|
|
88
|
+
elnOfferId: 'bd11b00a8d643e16b69c308360e5236b'
|
|
89
|
+
},
|
|
90
|
+
price: {
|
|
91
|
+
offerIndex: 0,
|
|
92
|
+
isStrike: false,
|
|
93
|
+
comparable: {
|
|
94
|
+
annualMileage: 10000,
|
|
95
|
+
firstInstallment: ' ',
|
|
96
|
+
paybackPeriod: 48,
|
|
97
|
+
withAddServices: ' ',
|
|
98
|
+
withTransportation: ' '
|
|
99
|
+
},
|
|
100
|
+
checkout: {
|
|
101
|
+
warrantyRates: [
|
|
102
|
+
0,
|
|
103
|
+
0,
|
|
104
|
+
0
|
|
105
|
+
],
|
|
106
|
+
warrantyPackage: 0,
|
|
107
|
+
warrantyPeriod: 1,
|
|
108
|
+
admissionService: 0,
|
|
109
|
+
licensePlateFee: 0
|
|
110
|
+
},
|
|
111
|
+
common: {
|
|
112
|
+
firstRegistration: ' ',
|
|
113
|
+
mileage: 0,
|
|
114
|
+
currentSalesPrice: 30666,
|
|
115
|
+
highestPrice: 34232,
|
|
116
|
+
isStrikeShown: true,
|
|
117
|
+
isHybridOrElectric: false
|
|
118
|
+
},
|
|
119
|
+
financing: {
|
|
120
|
+
grossLoanAmountWithoutFinalInstallment: 0,
|
|
121
|
+
purchasePrice: 0,
|
|
122
|
+
hasPaymentProtection: false,
|
|
123
|
+
paymentProtectionInsurance: 0,
|
|
124
|
+
monthlyInstallment: 142,
|
|
125
|
+
oldMonthlyInstallment: 180,
|
|
126
|
+
annualMileage: 25000,
|
|
127
|
+
firstInstallment: 11900,
|
|
128
|
+
withTransportation: false,
|
|
129
|
+
withAddServices: true,
|
|
130
|
+
addServicesCostRaw: 799,
|
|
131
|
+
addServicesCost: 799,
|
|
132
|
+
transportationCostRaw: 499,
|
|
133
|
+
transportationCost: 499,
|
|
134
|
+
withFinalInstallment: true,
|
|
135
|
+
paybackPeriod: 72,
|
|
136
|
+
rawPaybackPeriod: 72,
|
|
137
|
+
nominalInterestRate: 3.92,
|
|
138
|
+
annualPercentageRate: 6.99,
|
|
139
|
+
financialInstitution: 'Santander Consumer Bank AG, Santander-Platz 1, 41061 Mönchengladbach',
|
|
140
|
+
periodInterestRate: [
|
|
141
|
+
{
|
|
142
|
+
duration: 12,
|
|
143
|
+
recommended: 70,
|
|
144
|
+
current: 88,
|
|
145
|
+
inEUR: ' ',
|
|
146
|
+
value: 18766,
|
|
147
|
+
highestValue: 30124.16
|
|
148
|
+
},
|
|
149
|
+
{
|
|
150
|
+
duration: 24,
|
|
151
|
+
recommended: 66,
|
|
152
|
+
current: 77,
|
|
153
|
+
inEUR: ' ',
|
|
154
|
+
value: 18766,
|
|
155
|
+
highestValue: 26358.64
|
|
156
|
+
},
|
|
157
|
+
{
|
|
158
|
+
duration: 36,
|
|
159
|
+
recommended: 60,
|
|
160
|
+
current: 66,
|
|
161
|
+
inEUR: ' ',
|
|
162
|
+
value: 18766,
|
|
163
|
+
highestValue: 22593.12
|
|
164
|
+
},
|
|
165
|
+
{
|
|
166
|
+
duration: 48,
|
|
167
|
+
recommended: 50,
|
|
168
|
+
current: 60,
|
|
169
|
+
inEUR: ' ',
|
|
170
|
+
value: 17920.2,
|
|
171
|
+
highestValue: 20539.2
|
|
172
|
+
},
|
|
173
|
+
{
|
|
174
|
+
duration: 60,
|
|
175
|
+
recommended: 40,
|
|
176
|
+
current: 50,
|
|
177
|
+
inEUR: ' ',
|
|
178
|
+
value: 14933.5,
|
|
179
|
+
highestValue: 17116
|
|
180
|
+
},
|
|
181
|
+
{
|
|
182
|
+
duration: 72,
|
|
183
|
+
recommended: 30,
|
|
184
|
+
current: 40,
|
|
185
|
+
inEUR: ' ',
|
|
186
|
+
value: 11946.8,
|
|
187
|
+
highestValue: 13692.8
|
|
188
|
+
},
|
|
189
|
+
{
|
|
190
|
+
duration: 84,
|
|
191
|
+
recommended: 20,
|
|
192
|
+
current: 30,
|
|
193
|
+
inEUR: ' ',
|
|
194
|
+
value: 8960.1,
|
|
195
|
+
highestValue: 10269.6
|
|
196
|
+
},
|
|
197
|
+
{
|
|
198
|
+
duration: 96,
|
|
199
|
+
recommended: 10,
|
|
200
|
+
current: 20,
|
|
201
|
+
inEUR: ' ',
|
|
202
|
+
value: 5973.4,
|
|
203
|
+
highestValue: 6846.4
|
|
204
|
+
}
|
|
205
|
+
],
|
|
206
|
+
closingCosts: 0,
|
|
207
|
+
offersFinancing: true,
|
|
208
|
+
rateMode: 'dealer'
|
|
209
|
+
},
|
|
210
|
+
buy: {
|
|
211
|
+
withTransportation: false,
|
|
212
|
+
withAddServices: true,
|
|
213
|
+
withoutAddServices: true,
|
|
214
|
+
transportationCost: 499,
|
|
215
|
+
addServicesCost: 799,
|
|
216
|
+
currentSalesPriceExtra: 30666,
|
|
217
|
+
highestPriceExtra: 34232,
|
|
218
|
+
extraCost: 0
|
|
219
|
+
},
|
|
220
|
+
leasing: {
|
|
221
|
+
RWG: 7,
|
|
222
|
+
maxAge: 24,
|
|
223
|
+
maxMileage: 1000000,
|
|
224
|
+
isActive: true,
|
|
225
|
+
withTransportation: false,
|
|
226
|
+
withAddServices: false,
|
|
227
|
+
addServicesCostRaw: 799,
|
|
228
|
+
transportationCostRaw: 499,
|
|
229
|
+
addServicesCost: 799,
|
|
230
|
+
transportationCost: 499,
|
|
231
|
+
monthlyAddServices: 0,
|
|
232
|
+
monthlyTransportation: 0,
|
|
233
|
+
monthlyInstallment: 441,
|
|
234
|
+
oldMonthlyInstallment: 526,
|
|
235
|
+
firstInstallment: 20,
|
|
236
|
+
firstInstallmentMax: 2000,
|
|
237
|
+
annualMileage: 10000,
|
|
238
|
+
paybackPeriodRange: [
|
|
239
|
+
30,
|
|
240
|
+
36,
|
|
241
|
+
42,
|
|
242
|
+
48,
|
|
243
|
+
54,
|
|
244
|
+
60
|
|
245
|
+
],
|
|
246
|
+
paybackPeriod: 48,
|
|
247
|
+
santanderPayBackMin: 250,
|
|
248
|
+
nominalInterestRate: 6.78,
|
|
249
|
+
financialInstitution: 'Santander Consumer Bank AG, Santander-Platz 1, 41061 Mönchengladbach',
|
|
250
|
+
grossLoanAmountWithoutFinalInstallment: 0,
|
|
251
|
+
hasPaymentProtection: false,
|
|
252
|
+
paymentProtectionInsurance: 1100,
|
|
253
|
+
leasingMode: 'default',
|
|
254
|
+
currentSalesPrice: 30666
|
|
255
|
+
},
|
|
256
|
+
abo: {
|
|
257
|
+
paybackPeriod: 6,
|
|
258
|
+
annualMileage: 10000
|
|
259
|
+
},
|
|
260
|
+
firstRegistration: ' ',
|
|
261
|
+
mileage: 0,
|
|
262
|
+
currentSalesPrice: 30666,
|
|
263
|
+
highestPrice: 34232,
|
|
264
|
+
isStrikeShown: true,
|
|
265
|
+
carId: 'c4c9141a-5e4c-4d75-9d0f-c2f1b8f31241',
|
|
266
|
+
offerName: 'financing',
|
|
267
|
+
vehicleId: 'c4c9141a-5e4c-4d75-9d0f-c2f1b8f31241',
|
|
268
|
+
vatRate: 19,
|
|
269
|
+
mlCurrentSalesPricePredicted: ' ',
|
|
270
|
+
historyPriceDifference: 3566,
|
|
271
|
+
historyPriceDifferencePerCent: 10,
|
|
272
|
+
margin: 30666,
|
|
273
|
+
toRound: false
|
|
274
|
+
},
|
|
275
|
+
internalNumber: '118_92436S/3243',
|
|
276
|
+
vin: '',
|
|
277
|
+
isOnline: true,
|
|
278
|
+
firstIsOnline: 1675668230,
|
|
279
|
+
url: '/search/vehicle/c4c9141a-5e4c-4d75-9d0f-c2f1b8f31241',
|
|
280
|
+
relativeScore: 0,
|
|
281
|
+
baseUrl: '',
|
|
282
|
+
offerSource: '',
|
|
283
|
+
crawledAt: '',
|
|
284
|
+
ownerName: 'Guardian of Auto.de',
|
|
285
|
+
modificationDate: '18.05.2023',
|
|
286
|
+
seoText: ''
|
|
287
|
+
}
|
|
288
|
+
];
|
|
289
|
+
const favoritesIDs = [
|
|
290
|
+
'b359d74f-bb96-4fca-9539-579792fe7c36'
|
|
291
|
+
];
|
|
292
|
+
const getFavoriteCarsMock = jest.fn();
|
|
293
|
+
|
|
294
|
+
const aggStatsData = observable({
|
|
295
|
+
'b359d74f-bb96-4fca-9539-579792fe7c36': {
|
|
296
|
+
carId: 'b359d74f-bb96-4fca-9539-579792fe7c36',
|
|
297
|
+
totalFavCount: 3,
|
|
298
|
+
totalCarImpCount: 7399,
|
|
299
|
+
slidingCarImpCount: 10
|
|
300
|
+
},
|
|
301
|
+
get() {
|
|
302
|
+
return {
|
|
303
|
+
'b359d74f-bb96-4fca-9539-579792fe7c36': {
|
|
304
|
+
carId: 'b359d74f-bb96-4fca-9539-579792fe7c36',
|
|
305
|
+
totalFavCount: 3,
|
|
306
|
+
totalCarImpCount: 7399,
|
|
307
|
+
slidingCarImpCount: 10
|
|
308
|
+
}
|
|
309
|
+
};
|
|
310
|
+
}
|
|
311
|
+
});
|
|
312
|
+
const mockProps = {
|
|
313
|
+
t,
|
|
314
|
+
LinkRouter,
|
|
315
|
+
PLACEHOLDER_IMAGE_SMALL_URL: 'PLACEHOLDER_IMAGE_SMALL_URL',
|
|
316
|
+
pageNumberKey: 'pageNumber',
|
|
317
|
+
favoriteStore: { favoriteCars, favoritesIDs, showList: true, getFavouriteCars: getFavoriteCarsMock, getFavoritesIDs: jest.fn() },
|
|
318
|
+
appStore: {},
|
|
319
|
+
carsStore: { aggStatsData, getAggStatsData: jest.fn() },
|
|
320
|
+
imagesStore: { getSupportedImageFormat: jest.fn() }
|
|
321
|
+
};
|
|
322
|
+
|
|
323
|
+
describe('FavoriteSection', () => {
|
|
324
|
+
test('calls getFavouriteCars when component is mounted', () => {
|
|
325
|
+
render(<FavoriteSection {...mockProps} />);
|
|
326
|
+
expect(mockProps.favoriteStore.getFavouriteCars).toHaveBeenCalledTimes(1);
|
|
327
|
+
});
|
|
328
|
+
test('calls getFavoritesIDs and getAggStatsData when favoritesIDs is empty', async () => {
|
|
329
|
+
const favoritesIDs: string[] = [];
|
|
330
|
+
const props = {
|
|
331
|
+
t,
|
|
332
|
+
LinkRouter,
|
|
333
|
+
PLACEHOLDER_IMAGE_SMALL_URL: 'PLACEHOLDER_IMAGE_SMALL_URL',
|
|
334
|
+
pageNumberKey: 4,
|
|
335
|
+
favoriteStore: { favoriteCars, favoritesIDs, showList: true, getFavouriteCars: getFavoriteCarsMock, getFavoritesIDs: jest.fn() },
|
|
336
|
+
appStore: {},
|
|
337
|
+
carsStore: { aggStatsData, getAggStatsData: jest.fn() },
|
|
338
|
+
imagesStore: { getSupportedImageFormat: jest.fn() }
|
|
339
|
+
};
|
|
340
|
+
props.favoriteStore.getFavoritesIDs.mockResolvedValueOnce(['b359d74f-bb96-4fca-9539-579792fe7c36']);
|
|
341
|
+
|
|
342
|
+
render(<FavoriteSection {...props} />);
|
|
343
|
+
expect(props.favoriteStore.getFavoritesIDs).toHaveBeenCalledTimes(1);
|
|
344
|
+
expect(mockProps.carsStore.getAggStatsData).toHaveBeenCalledTimes(1);
|
|
345
|
+
expect(mockProps.carsStore.getAggStatsData).toHaveBeenCalledWith(['b359d74f-bb96-4fca-9539-579792fe7c36']);
|
|
346
|
+
});
|
|
347
|
+
test('does not call getFavoritesIDs when favoritesIDs is not empty', async () => {
|
|
348
|
+
render(<FavoriteSection {...mockProps} />);
|
|
349
|
+
expect(mockProps.favoriteStore.getFavoritesIDs).not.toHaveBeenCalled();
|
|
350
|
+
});
|
|
351
|
+
test('returns the correct current page', () => {
|
|
352
|
+
const mockProps = {
|
|
353
|
+
t: jest.fn(),
|
|
354
|
+
LinkRouter: jest.fn(),
|
|
355
|
+
PLACEHOLDER_IMAGE_SMALL_URL: 'PLACEHOLDER_IMAGE_SMALL_URL',
|
|
356
|
+
pageNumberKey: 'pageNumber',
|
|
357
|
+
favoriteStore: { favoriteCars, favoritesIDs, showList: true, getFavouriteCars: getFavoriteCarsMock, getFavoritesIDs: jest.fn() },
|
|
358
|
+
appStore: {},
|
|
359
|
+
carsStore: {
|
|
360
|
+
aggStatsData: {},
|
|
361
|
+
getAggStatsData: jest.fn()
|
|
362
|
+
},
|
|
363
|
+
imagesStore: {
|
|
364
|
+
getSupportedImageFormat: jest.fn()
|
|
365
|
+
}
|
|
366
|
+
};
|
|
367
|
+
jest.spyOn(qs, 'parse').mockReturnValueOnce({ pageNumber: '3' });
|
|
368
|
+
const favoriteSectionInstance = new FavoriteSection(mockProps);
|
|
369
|
+
const currentPage = favoriteSectionInstance.getCurrentPage();
|
|
370
|
+
expect(currentPage).toBe(3);
|
|
371
|
+
});
|
|
372
|
+
|
|
373
|
+
});
|
|
@@ -10,7 +10,8 @@ const expectedResultCDP = [
|
|
|
10
10
|
max: 21666,
|
|
11
11
|
value: 16100,
|
|
12
12
|
unitName: 'modals:financing.euro',
|
|
13
|
-
caption: 'modals:financing.firstInstallment'
|
|
13
|
+
caption: 'modals:financing.firstInstallment',
|
|
14
|
+
withRangeLimit: true
|
|
14
15
|
},
|
|
15
16
|
{
|
|
16
17
|
name: 'annualMileage',
|
|
@@ -33,7 +34,8 @@ const expectedResultCheckout = [
|
|
|
33
34
|
max: 21666,
|
|
34
35
|
value: 16100,
|
|
35
36
|
unitName: 'modals:financing.euro',
|
|
36
|
-
caption: 'modals:financing.firstInstallment'
|
|
37
|
+
caption: 'modals:financing.firstInstallment',
|
|
38
|
+
withRangeLimit: true
|
|
37
39
|
}
|
|
38
40
|
]
|
|
39
41
|
|
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.144",
|
|
4
4
|
"description": "UI components for the auto.de project",
|
|
5
5
|
"main": "index.ts",
|
|
6
6
|
"module": "dist/common.js",
|
|
@@ -82,6 +82,7 @@
|
|
|
82
82
|
"@types/react": "^17.0.2",
|
|
83
83
|
"@types/react-dom": "^17.0.2",
|
|
84
84
|
"@types/react-lazyload": "^2.5.0",
|
|
85
|
+
"@types/react-scroll": "^1.8.7",
|
|
85
86
|
"@types/react-select": "^3.0.2",
|
|
86
87
|
"@types/react-slick": "^0.23.4 ",
|
|
87
88
|
"autoprefixer": "^9.6.0",
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
@import '../../../../theme/mixins.styl'
|
|
2
|
+
|
|
3
|
+
.wrapFavorites
|
|
4
|
+
border: none !important;
|
|
5
|
+
|
|
6
|
+
.favoriteBtn
|
|
7
|
+
height: 30px;
|
|
8
|
+
font-size: 13px;
|
|
9
|
+
text-transform: none !important
|
|
10
|
+
font-weight: 400 !important;
|
|
11
|
+
|
|
12
|
+
+media-tablet-landscape-up()
|
|
13
|
+
height: 38px;
|
|
14
|
+
font-size: 14px;
|
|
15
|
+
|
|
16
|
+
.btnCarToFavorites
|
|
17
|
+
height: 38px;
|
|
18
|
+
min-width: 160px !important;
|
|
19
|
+
font-size: 13px !important;
|
|
20
|
+
+media-tablet-landscape-up()
|
|
21
|
+
min-width: 224px !important;
|
|
22
|
+
font-size: 14px !important;
|
|
@@ -0,0 +1,112 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
import { toJS } from 'mobx';
|
|
3
|
+
import qs from 'qs';
|
|
4
|
+
import _get from 'lodash/get';
|
|
5
|
+
import DashboardSection from '../../../containers/DasboardSection/DashboardSection';
|
|
6
|
+
import styles from './FavoriteSection.styl';
|
|
7
|
+
import { isMobileOnly } from 'react-device-detect';
|
|
8
|
+
import { VehicleSmallCard, Button } from '../../../../../common';
|
|
9
|
+
|
|
10
|
+
interface ITFunction {
|
|
11
|
+
<T = string>(key: string, options?: object): T;
|
|
12
|
+
<T = string>(keys: string[], options?: object): T;
|
|
13
|
+
}
|
|
14
|
+
|
|
15
|
+
interface IFavoriteSectionProps {
|
|
16
|
+
favoriteStore: any;
|
|
17
|
+
carsStore: any;
|
|
18
|
+
appStore: any;
|
|
19
|
+
imagesStore: any;
|
|
20
|
+
t?: ITFunction;
|
|
21
|
+
PLACEHOLDER_IMAGE_SMALL_URL: string;
|
|
22
|
+
pageNumberKey: any;
|
|
23
|
+
LinkRouter: any;
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
class FavoriteSection extends React.Component<IFavoriteSectionProps, {}> {
|
|
27
|
+
componentDidMount() {
|
|
28
|
+
const currentPage = this.getCurrentPage();
|
|
29
|
+
this.getCarsForPage(currentPage);
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
getCarsForPage = (page: number): void => {
|
|
33
|
+
const { favoriteStore, carsStore } = this.props;
|
|
34
|
+
if (page) {
|
|
35
|
+
favoriteStore.getFavouriteCars(page);
|
|
36
|
+
|
|
37
|
+
if (!favoriteStore.favoritesIDs.length) {
|
|
38
|
+
favoriteStore.getFavoritesIDs().then((favoritesIDs: any) => {
|
|
39
|
+
carsStore.getAggStatsData(favoritesIDs);
|
|
40
|
+
});
|
|
41
|
+
} else carsStore.getAggStatsData(favoriteStore.favoritesIDs);
|
|
42
|
+
}
|
|
43
|
+
};
|
|
44
|
+
|
|
45
|
+
getCurrentPage = () => {
|
|
46
|
+
const { pageNumberKey } = this.props;
|
|
47
|
+
const pageFromQuery = qs.parse(location.search, { ignoreQueryPrefix: true })[pageNumberKey];
|
|
48
|
+
if (!pageFromQuery) return 1;
|
|
49
|
+
const page = Number(pageFromQuery);
|
|
50
|
+
return page > 0 ? page : 1;
|
|
51
|
+
};
|
|
52
|
+
|
|
53
|
+
onCarSelectFavorite = (url: string) => window.open(`/search/vehicle/${url}`, '_blank');
|
|
54
|
+
|
|
55
|
+
private renderFavorites = () => {
|
|
56
|
+
const { t, appStore: { language }, carsStore, imagesStore, favoriteStore, PLACEHOLDER_IMAGE_SMALL_URL, LinkRouter } = this.props;
|
|
57
|
+
const favoriteCars = toJS(favoriteStore.favoriteCars);
|
|
58
|
+
return favoriteCars.map((car: any, key: any) => {
|
|
59
|
+
const carId = _get(car, 'id');
|
|
60
|
+
const mainImageId = _get(car, 'mainImageId');
|
|
61
|
+
const src = !!mainImageId && !!car.imagesCount
|
|
62
|
+
? imagesStore.getSupportedImageFormat(carId, mainImageId, 'small')
|
|
63
|
+
: PLACEHOLDER_IMAGE_SMALL_URL;
|
|
64
|
+
const vehicleProps = {
|
|
65
|
+
...car,
|
|
66
|
+
t,
|
|
67
|
+
language,
|
|
68
|
+
src,
|
|
69
|
+
linkTag: LinkRouter,
|
|
70
|
+
showSlider: false,
|
|
71
|
+
showOfferBtn: true,
|
|
72
|
+
showFavoriteStar: false,
|
|
73
|
+
priceSubMtl: !isMobileOnly ? t('vehicleProps:value.priceSub') : null,
|
|
74
|
+
stats: {
|
|
75
|
+
imagesCount: _get(car, 'imagesCount'),
|
|
76
|
+
statsData: carsStore.aggStatsData.get(car.id)
|
|
77
|
+
},
|
|
78
|
+
i18nPrefixForPriceRating: 'common:',
|
|
79
|
+
className: styles.wrapFavorites,
|
|
80
|
+
classButton: styles.favoriteBtn,
|
|
81
|
+
onDetailsClick: this.onCarSelectFavorite,
|
|
82
|
+
vehicleComponentName: 'favorite'
|
|
83
|
+
};
|
|
84
|
+
|
|
85
|
+
return (key === 0) && <VehicleSmallCard key={`favoriteCar${carId}`} {...vehicleProps} />;
|
|
86
|
+
});
|
|
87
|
+
};
|
|
88
|
+
|
|
89
|
+
render(): JSX.Element {
|
|
90
|
+
const { t, favoriteStore, LinkRouter } = this.props;
|
|
91
|
+
|
|
92
|
+
return (
|
|
93
|
+
<>
|
|
94
|
+
{favoriteStore.showList ? (
|
|
95
|
+
<DashboardSection
|
|
96
|
+
title={t('DashboardPage:favoriteTitle')}
|
|
97
|
+
link={
|
|
98
|
+
<LinkRouter to='/favourites'>
|
|
99
|
+
<Button className={styles.btnCarToFavorites} variant='outlined'>
|
|
100
|
+
{t('vehicleProps:title.toFavoritesCar')}
|
|
101
|
+
</Button>
|
|
102
|
+
</LinkRouter>}
|
|
103
|
+
>
|
|
104
|
+
{this.renderFavorites()}
|
|
105
|
+
</DashboardSection>
|
|
106
|
+
) : false}
|
|
107
|
+
</>
|
|
108
|
+
);
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
export default FavoriteSection;
|
package/source/components/UserDashboardPage/sections/RequestedCarsSection/RequestedCarsSection.tsx
CHANGED
|
@@ -36,7 +36,7 @@ const RequestedCarsSection = ({ t, getSupportedImageFormat, requestedCars, redir
|
|
|
36
36
|
const renderItems = () => {
|
|
37
37
|
if (requestedCars && requestedCars.length > 0) {
|
|
38
38
|
const carsCard = requestedCars.map((car) => {
|
|
39
|
-
if (car && car.car) {
|
|
39
|
+
if (car && car.car.mainData && car.car.metaData) {
|
|
40
40
|
const { car: { mainData: { make, model, subModel } } } = car;
|
|
41
41
|
const { car: { _id, metaData: { mainImageId } } } = car;
|
|
42
42
|
const { buyingType, paybackPeriod, monthlyInstallment, request, currentSalesPrice } = car;
|
|
@@ -120,4 +120,5 @@ const RequestedCarsSection = ({ t, getSupportedImageFormat, requestedCars, redir
|
|
|
120
120
|
</>
|
|
121
121
|
);
|
|
122
122
|
};
|
|
123
|
+
|
|
123
124
|
export default RequestedCarsSection;
|
|
@@ -183,7 +183,7 @@ const VehiclePrice: React.FC<IVehiclePriceSectionProps> = (props: IVehiclePriceS
|
|
|
183
183
|
}
|
|
184
184
|
] : '';
|
|
185
185
|
|
|
186
|
-
const priceData = combineRefAlternative ? [
|
|
186
|
+
const priceData:any = combineRefAlternative ? [
|
|
187
187
|
...priceItemsGlobal,
|
|
188
188
|
{
|
|
189
189
|
isTotal: true,
|
|
@@ -3,7 +3,7 @@ import _get from 'lodash/get';
|
|
|
3
3
|
import _startsWith from 'lodash/startsWith';
|
|
4
4
|
import _debounce from 'lodash/debounce';
|
|
5
5
|
import qs from 'qs';
|
|
6
|
-
import { isEqual } from 'lodash';
|
|
6
|
+
import { isArray, isEqual } from 'lodash';
|
|
7
7
|
import { checkRangeValuesOnEqual, getGroupValuesForQuery } from '../../../../framework/utils/CommonUtils';
|
|
8
8
|
import { FilterBlockFactory } from '../../../SearchFilters/common/FilterBlock/FilterBlockFactory';
|
|
9
9
|
import { FilterGroups, IFilters } from '../../../SearchFilters/FiltersFactory';
|
|
@@ -83,11 +83,11 @@ class FiltersContainer extends React.Component<IFiltersContainerProps, {}> {
|
|
|
83
83
|
|
|
84
84
|
if (activeSort !== activeSorting) {
|
|
85
85
|
// activeSorting = activeSort; // TODO make a function to change at searchStore
|
|
86
|
-
setActiveSorting(activeSort);
|
|
86
|
+
setActiveSorting(activeSort as string);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
clearSearchState(!activeSort);
|
|
90
|
-
search(filters, pageNumber || 1, true);
|
|
90
|
+
search(filters, Number(pageNumber) || 1, true);
|
|
91
91
|
}
|
|
92
92
|
|
|
93
93
|
this.updateFinancingSearchConfig();
|
|
@@ -194,41 +194,46 @@ class FiltersContainer extends React.Component<IFiltersContainerProps, {}> {
|
|
|
194
194
|
if (paramsKeys.length) {
|
|
195
195
|
paramsKeys.forEach((filter: string) => {
|
|
196
196
|
const paramValue = paramsFromQuery[filter];
|
|
197
|
-
|
|
198
197
|
if (filter === MMS_GROUPS_KEY) { //tslint:disable-line
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
Object.keys(group).forEach((key: string) => {
|
|
205
|
-
changeFilterValue(key, group[key], index);
|
|
206
|
-
if (key === MANUFACTURER_KEY) {
|
|
207
|
-
getModelsInfoByMaker(group[key], true).then((response: any) => {
|
|
208
|
-
const models = response || [];
|
|
209
|
-
addModelsToFilters(models, index);
|
|
210
|
-
});
|
|
198
|
+
if (isArray(paramValue)) {
|
|
199
|
+
const stringParamValue: string[] = paramValue as string[];
|
|
200
|
+
stringParamValue.map((group: any, index: number) => {
|
|
201
|
+
if (index >= 1) {
|
|
202
|
+
if (filter === MMS_GROUPS_KEY) addMmsGroup();
|
|
211
203
|
}
|
|
204
|
+
|
|
205
|
+
Object.keys(group).forEach((key: string) => {
|
|
206
|
+
changeFilterValue(key, group[key], index);
|
|
207
|
+
if (key === MANUFACTURER_KEY) {
|
|
208
|
+
getModelsInfoByMaker(group[key], true).then((response: any) => {
|
|
209
|
+
const models = response || [];
|
|
210
|
+
addModelsToFilters(models, index);
|
|
211
|
+
});
|
|
212
|
+
}
|
|
213
|
+
});
|
|
212
214
|
});
|
|
213
|
-
}
|
|
215
|
+
}
|
|
214
216
|
} else if (filter === MM_GROUPS_EXCLUDE_KEY) {
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
217
|
+
if (isArray(paramValue)) {
|
|
218
|
+
const stringParamValue: string[] = paramValue as string[];
|
|
219
|
+
stringParamValue.map((group: any, index: number) => {
|
|
220
|
+
if (index >= 1) {
|
|
221
|
+
addMmExcludeGroup();
|
|
222
|
+
}
|
|
219
223
|
|
|
220
|
-
|
|
221
|
-
|
|
224
|
+
Object.keys(group).forEach((key: string) => {
|
|
225
|
+
changeFilterValue(key, group[key], index);
|
|
226
|
+
});
|
|
222
227
|
});
|
|
223
|
-
}
|
|
228
|
+
}
|
|
224
229
|
} else {
|
|
225
230
|
// Defines whether filter is range or not.
|
|
226
231
|
const isRange = rangeFiltersStrings.indexOf(filter) !== -1;
|
|
227
232
|
const isObject = objectFiltersStrings.indexOf(filter) !== -1;
|
|
228
233
|
|
|
229
234
|
// Transform url encoded param into range filter object.
|
|
230
|
-
const valueToSend = isRange ? qs.parse(paramValue, { ignoreQueryPrefix: true }) : paramValue;
|
|
231
|
-
changeFilterValue(filter, valueToSend);
|
|
235
|
+
const valueToSend = isRange ? qs.parse(paramValue as string, { ignoreQueryPrefix: true }) : paramValue;
|
|
236
|
+
changeFilterValue(filter, valueToSend as string);
|
|
232
237
|
if (isRange || isObject) { changeRangeFilterControls(filter, valueToSend); }
|
|
233
238
|
}
|
|
234
239
|
});
|
|
@@ -383,7 +388,7 @@ class FiltersContainer extends React.Component<IFiltersContainerProps, {}> {
|
|
|
383
388
|
const alternativeIDProps = {
|
|
384
389
|
t,
|
|
385
390
|
successTransition,
|
|
386
|
-
autoDeId: paramsFromQuery.autoDeId,
|
|
391
|
+
autoDeId: paramsFromQuery.autoDeId as string,
|
|
387
392
|
error: isErrorAlternativeField,
|
|
388
393
|
onChange: onAlternativeRedirect
|
|
389
394
|
};
|
|
@@ -394,7 +399,7 @@ class FiltersContainer extends React.Component<IFiltersContainerProps, {}> {
|
|
|
394
399
|
<div className={styles.titleAlternative}>
|
|
395
400
|
<div className={styles.titleWrap}>
|
|
396
401
|
<h3 className={styles.titleTextAlternative}>auto.de-ID</h3>
|
|
397
|
-
<Link to={
|
|
402
|
+
<Link to={`/alternative/detailed${locationSearch}`} className={styles.titleLink}>
|
|
398
403
|
{this.props.t('SearchPage:detailedSearch')}
|
|
399
404
|
</Link>
|
|
400
405
|
</div>
|
|
@@ -405,7 +410,7 @@ class FiltersContainer extends React.Component<IFiltersContainerProps, {}> {
|
|
|
405
410
|
<h3 className={styles.titleText}>{this.props.t('SearchPage:filterBy')}</h3>
|
|
406
411
|
</div>
|
|
407
412
|
{this.renderFilters()}
|
|
408
|
-
<Link className={styles.linkToDetailed} to={
|
|
413
|
+
<Link className={styles.linkToDetailed} to={`/${isAlternative ? 'alternative' : 'search'}/detailed${locationSearch}`}>{t('SearchPage:detailedSearch')}</Link>
|
|
409
414
|
</div>
|
|
410
415
|
);
|
|
411
416
|
}
|
|
@@ -420,8 +425,8 @@ const removeUnknownOptions = (options: any) => {
|
|
|
420
425
|
|
|
421
426
|
export default React.memo(FiltersContainer, (props, nextProps) => {
|
|
422
427
|
const { t, location, filters, aggregation } = props;
|
|
423
|
-
return t
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
428
|
+
return t === nextProps.t &&
|
|
429
|
+
location.search === nextProps.location.search &&
|
|
430
|
+
isEqual(aggregation, nextProps.aggregation) &&
|
|
431
|
+
isEqual(filters.MMS_GROUPS, nextProps.filters.MMS_GROUPS);
|
|
427
432
|
});
|