@bytebrand/fe-ui-core 4.2.48 → 4.2.50

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bytebrand/fe-ui-core",
3
- "version": "4.2.48",
3
+ "version": "4.2.50",
4
4
  "description": "UI components for the auto.de project",
5
5
  "main": "index.ts",
6
6
  "module": "dist/common.js",
@@ -49,10 +49,6 @@ export interface IVehiclePriceSectionProps {
49
49
  typeAlternative?: string;
50
50
  }
51
51
 
52
- export interface IPriceItemsProps {
53
- priceItemsProp: IVehiclePriceSectionProps[];
54
- }
55
-
56
52
  interface IPriceData {
57
53
  tooltipDescription?: string;
58
54
  perMonthOld?: any;
@@ -71,235 +67,217 @@ interface IPriceData {
71
67
  totalCurrent: number;
72
68
  }
73
69
 
74
- class VehiclePrice extends React.Component<IVehiclePriceSectionProps> {
70
+ const VehiclePrice: React.FC<IVehiclePriceSectionProps> = (props: IVehiclePriceSectionProps) => {
75
71
 
76
- onAddOfferClick = (event: any) => {
77
- const { id, mainImageId, buy: { currentSalesPriceExtra } } = this.props;
72
+ const onAddOfferClick = (event: any) => {
73
+ const { id, mainImageId, buy: { currentSalesPriceExtra } } = props;
78
74
  event.stopPropagation();
79
75
  event.preventDefault();
80
- this.props.onAddOfferToMainSlideClick(id, mainImageId, currentSalesPriceExtra, this.props);
76
+ props.onAddOfferToMainSlideClick(id, mainImageId, currentSalesPriceExtra, props);
81
77
  };
82
78
 
83
- onDetailsClick = (event: React.MouseEvent<HTMLButtonElement>) => {
84
- const { id, onDetailsClick } = this.props;
79
+ const onDetailsClick = (event: React.MouseEvent<HTMLButtonElement>) => {
80
+ const { id, onDetailsClick } = props;
85
81
  event.preventDefault();
86
82
  event.stopPropagation();
87
83
  onDetailsClick(id);
88
84
  };
89
85
 
90
- render(): React.ReactNode {
91
- const {
92
- t,
93
- combineRefAlternative,
94
- url,
95
- target,
96
- rel,
97
- isDealerSuperAdmin,
98
- linkTag,
99
- showOfferBtn,
100
- routeObj,
101
- toggleCarToCompare,
102
- toCompare,
103
- priceSubMtl,
104
- classButton,
105
- onRemoveClick,
106
- showCompareCheckboxes,
107
- vatRate,
108
- iconName,
109
- vehicleComponentName,
110
- financing: { monthlyInstallment, oldMonthlyInstallment },
111
- leasing: {
112
- monthlyInstallment: lMonthlyInstallment,
113
- oldMonthlyInstallment: lOldMonthlyInstallment,
114
- isActive: isLeasingActive
115
- },
116
- buy: {
117
- currentSalesPriceExtra = 0,
118
- highestPriceExtra = 0
119
- } = {},
120
- common: { isStrikeShown },
121
- typeAlternative,
122
- margin
123
- } = this.props;
86
+ const {
87
+ t,
88
+ combineRefAlternative,
89
+ url,
90
+ target,
91
+ rel,
92
+ isDealerSuperAdmin,
93
+ linkTag,
94
+ showOfferBtn,
95
+ routeObj,
96
+ toggleCarToCompare,
97
+ toCompare,
98
+ priceSubMtl,
99
+ classButton,
100
+ onRemoveClick,
101
+ showCompareCheckboxes,
102
+ vatRate,
103
+ iconName,
104
+ vehicleComponentName,
105
+ financing: { monthlyInstallment, oldMonthlyInstallment },
106
+ leasing: {
107
+ monthlyInstallment: lMonthlyInstallment,
108
+ oldMonthlyInstallment: lOldMonthlyInstallment,
109
+ isActive: isLeasingActive
110
+ },
111
+ buy: {
112
+ currentSalesPriceExtra = 0,
113
+ highestPriceExtra = 0
114
+ } = {},
115
+ common: { isStrikeShown },
116
+ typeAlternative,
117
+ margin
118
+ } = props;
119
+
120
+ const vehiclePriceSectionClassName = classnames(
121
+ styles.vehiclePriceSection,
122
+ { [styles.vehiclePriceSectionSearch]: vehicleComponentName === 'search' || vehicleComponentName === 'myVehicles' },
123
+ { [styles.vehiclePriceSectionFavorite]: vehicleComponentName === 'favorite' },
124
+ { [styles.vehiclePriceSectionRecently]: vehicleComponentName === 'recently' || vehicleComponentName === 'landing' },
125
+ { [styles.vehiclePriceTitleMain]: vehicleComponentName === 'main' }
126
+ );
127
+
128
+ const vehiclePriceTitleClassName = classnames(
129
+ styles.vehiclePriceTitle,
130
+ { [styles.vehiclePriceTitleFavorite]: vehicleComponentName === 'favorite' },
131
+ { [styles.vehiclePriceTitleRecently]: vehicleComponentName === 'recently' },
132
+ { [styles.vehiclePriceTitleLanding]: vehicleComponentName === 'landing' || vehicleComponentName === 'main' },
133
+ { [styles.vehiclePriceTitleSearch]: vehicleComponentName === 'search' || vehicleComponentName === 'myVehicles' }
134
+ );
124
135
 
125
- const vehiclePriceSectionClassName = classnames(
126
- styles.vehiclePriceSection,
127
- { [styles.vehiclePriceSectionSearch]: vehicleComponentName === 'search' || vehicleComponentName === 'myVehicles' },
128
- { [styles.vehiclePriceSectionFavorite]: vehicleComponentName === 'favorite' },
129
- { [styles.vehiclePriceSectionRecently]: vehicleComponentName === 'recently' || vehicleComponentName === 'landing' },
130
- { [styles.vehiclePriceTitleMain]: vehicleComponentName === 'main' }
131
- );
136
+ const buttonClassNames = classnames(
137
+ classButton,
138
+ styles.buttonDetails,
139
+ { [styles.isAlternativeButton]: typeAlternative }
140
+ );
132
141
 
133
- const vehiclePriceTitleClassName = classnames(
134
- styles.vehiclePriceTitle,
135
- { [styles.vehiclePriceTitleFavorite]: vehicleComponentName === 'favorite' },
136
- { [styles.vehiclePriceTitleRecently]: vehicleComponentName === 'recently' },
137
- { [styles.vehiclePriceTitleLanding]: vehicleComponentName === 'landing' || vehicleComponentName === 'main' },
138
- { [styles.vehiclePriceTitleSearch]: vehicleComponentName === 'search' || vehicleComponentName === 'myVehicles' }
139
- );
142
+ const offerBtnVariantCondition = vehicleComponentName === 'recently' ||
143
+ vehicleComponentName === 'landing' ||
144
+ vehicleComponentName === 'main' ? 'outlined' : 'contained';
140
145
 
141
- const priceItemsGlobal = [
142
- {
143
- perMonthOld: oldMonthlyInstallment,
144
- perMonthCurrent: monthlyInstallment,
145
- title: t('vehicleProps:title.financing'),
146
- prefixOldPrice: vehicleComponentName === 'search' && !isMobileOnly && t('vehicleProps:value.prefixOldPrice'),
147
- postfix: '3',
148
- priceSub: priceSubMtl,
149
- tooltipDescription: !combineRefAlternative && t('vehicleProps:title.financingDescription')
150
- },
151
- {
152
- perMonthOld: lOldMonthlyInstallment,
153
- perMonthCurrent: lMonthlyInstallment,
154
- prefixOldPrice: vehicleComponentName === 'search' && !isMobileOnly && t('vehicleProps:value.prefixOldPrice'),
155
- postfix: '1,3',
156
- isPriceDisable: !isLeasingActive,
157
- title: t('vehicleProps:title.leasing'),
158
- priceSub: priceSubMtl,
159
- tooltipDescription: !combineRefAlternative && t('vehicleProps:title.leasingDescription')
160
- }
161
- ];
162
146
 
163
- // const showAboCondition = vehicleComponentName !== 'favorite' &&
164
- // vehicleComponentName !== 'recently' &&
165
- // vehicleComponentName !== 'search';
166
- const showAboCondition = false;
147
+ const priceItemsGlobal = [
148
+ {
149
+ perMonthOld: oldMonthlyInstallment,
150
+ perMonthCurrent: monthlyInstallment,
151
+ title: t('vehicleProps:title.financing'),
152
+ prefixOldPrice: vehicleComponentName === 'search' && !isMobileOnly && t('vehicleProps:value.prefixOldPrice'),
153
+ postfix: '3',
154
+ priceSub: priceSubMtl,
155
+ tooltipDescription: !combineRefAlternative && t('vehicleProps:title.financingDescription')
156
+ },
157
+ {
158
+ perMonthOld: lOldMonthlyInstallment,
159
+ perMonthCurrent: lMonthlyInstallment,
160
+ prefixOldPrice: vehicleComponentName === 'search' && !isMobileOnly && t('vehicleProps:value.prefixOldPrice'),
161
+ postfix: '1,3',
162
+ isPriceDisable: !isLeasingActive,
163
+ title: t('vehicleProps:title.leasing'),
164
+ priceSub: priceSubMtl,
165
+ tooltipDescription: !combineRefAlternative && t('vehicleProps:title.leasingDescription')
166
+ }
167
+ ];
167
168
 
168
- const Abo = showAboCondition ? [
169
- {
170
- perMonthOld: oldMonthlyInstallment,
171
- perMonthCurrent: monthlyInstallment,
172
- isNewPriceCategory: true,
173
- showAboIcon: true,
174
- isPriceDisable: true,
175
- positionY: 'top',
176
- title: t('vehicleProps:title.abo'),
177
- tooltipDescription: t('vehicleProps:title.aboDescription')
178
- }
179
- ] : '';
169
+ // const showAboCondition = vehicleComponentName !== 'favorite' &&
170
+ // vehicleComponentName !== 'recently' &&
171
+ // vehicleComponentName !== 'search';
172
+ const showAboCondition = false;
180
173
 
181
- const priceData: IPriceData[] = combineRefAlternative ? [
182
- ...priceItemsGlobal,
183
- {
184
- isTotal: true,
185
- totalCurrent: currentSalesPriceExtra,
186
- postfix: !!vatRate ? '1' : '',
187
- title: t('vehicleProps:title.buy'),
188
- isAlternativeText: t('vehicleProps:title.margeInkl')
189
- },
190
- {
191
- isTotal: true,
192
- totalCurrent: margin ? margin : currentSalesPriceExtra,
193
- title: t('vehicleProps:title.marge')
194
- }
195
- ] : [
196
- ...priceItemsGlobal,
197
- ...Abo,
198
- {
199
- isTotal: true,
200
- totalCurrent: currentSalesPriceExtra,
201
- positionY: 'top',
202
- postfix: !!vatRate ? '1' : '',
203
- title: t('vehicleProps:title.buy'),
204
- tooltipDescription: t('vehicleProps:title.buyDescription')
205
- }
206
- ];
174
+ const Abo = showAboCondition ? [
175
+ {
176
+ perMonthOld: oldMonthlyInstallment,
177
+ perMonthCurrent: monthlyInstallment,
178
+ isNewPriceCategory: true,
179
+ showAboIcon: true,
180
+ isPriceDisable: true,
181
+ positionY: 'top',
182
+ title: t('vehicleProps:title.abo'),
183
+ tooltipDescription: t('vehicleProps:title.aboDescription')
184
+ }
185
+ ] : '';
207
186
 
208
- const ListPrices = priceData.map((
187
+ const priceData = combineRefAlternative ? [
188
+ ...priceItemsGlobal,
189
+ {
190
+ isTotal: true,
191
+ totalCurrent: currentSalesPriceExtra,
192
+ postfix: !!vatRate ? '1' : '',
193
+ title: t('vehicleProps:title.buy'),
194
+ isAlternativeText: t('vehicleProps:title.margeInkl')
195
+ },
209
196
  {
210
- title,
211
- priceSub,
212
- prefixOldPrice,
213
- totalCurrent,
214
- tooltipDescription,
215
- perMonthOld,
216
- isAlternativeText,
217
- perMonthCurrent,
218
- showAboIcon,
219
- isPriceDisable,
220
- isTotal,
221
- isNewPriceCategory,
222
- positionY,
223
- postfix
224
- }) => {
225
- return (
197
+ isTotal: true,
198
+ totalCurrent: margin ? margin : currentSalesPriceExtra,
199
+ title: t('vehicleProps:title.marge')
200
+ }
201
+ ] : [
202
+ ...priceItemsGlobal,
203
+ ...Abo,
204
+ {
205
+ isTotal: true,
206
+ totalCurrent: currentSalesPriceExtra,
207
+
208
+ postfix: !!vatRate ? '1' : '',
209
+ title: t('vehicleProps:title.buy'),
210
+ tooltipDescription: t('vehicleProps:title.buyDescription')
211
+ }
212
+ ];
213
+
214
+ return (
215
+ <section className={vehiclePriceSectionClassName}>
216
+ {vehicleComponentName === 'favorite' && showCompareCheckboxes && (
217
+ <CheckboxMaterial
218
+ checked={toCompare}
219
+ onChange={toggleCarToCompare}
220
+ labelPlacement='start'
221
+ label={t('FavoritesPage:toCompare')}
222
+ formControlClassName={styles.wrapCheckbox}
223
+ />
224
+ )}
225
+ {vehicleComponentName !== 'favorite' && vehicleComponentName !== 'search' && !isMobileOnly && (
226
+ <span className={vehiclePriceTitleClassName}>{t('vehicleProps:title.monthlyFrom')}</span>
227
+ )}
228
+ {isMobileOnly && !showCompareCheckboxes && (
229
+ <span className={vehiclePriceTitleClassName}>{t('vehicleProps:title.monthlyFrom')}</span>
230
+ )}
231
+ {priceData.map((props: any) => (
226
232
  <VehiclePriceItem
227
- tooltipDescription={tooltipDescription}
228
- key={title}
229
- priceTitle={title}
230
- isPriceDisable={isPriceDisable}
231
- perMonthOld={perMonthOld}
232
- perMonthCurrent={perMonthCurrent}
233
- isNewPriceCategory={isNewPriceCategory}
234
- isAlternativeText={isAlternativeText}
235
- showAboIcon={showAboIcon}
233
+ tooltipDescription={props.tooltipDescription}
234
+ key={props.title}
235
+ priceTitle={props.title}
236
+ isPriceDisable={props.isPriceDisable}
237
+ perMonthOld={props.perMonthOld}
238
+ perMonthCurrent={props.perMonthCurrent}
239
+ isNewPriceCategory={props.isNewPriceCategory}
240
+ isAlternativeText={props.isAlternativeText}
241
+ showAboIcon={props.showAboIcon}
236
242
  totalOld={highestPriceExtra}
237
- isTotal={isTotal}
238
- priceSub={priceSub}
239
- positionY={positionY}
243
+ isTotal={props.isTotal}
244
+ priceSub={props.priceSub}
245
+ positionY={props.positionY}
240
246
  url={url}
241
247
  target={target}
242
248
  rel={rel}
243
249
  isStrikeShown={isStrikeShown}
244
250
  iconName={iconName}
245
- prefixOldPrice={prefixOldPrice}
246
- totalCurrent={totalCurrent}
247
- postfix={postfix}
251
+ prefixOldPrice={props.prefixOldPrice}
252
+ totalCurrent={props.totalCurrent}
253
+ postfix={props.postfix}
248
254
  linkTag={linkTag}
249
255
  routeObj={routeObj}
250
256
  vehicleComponentName={vehicleComponentName}
251
257
  combineRefAlternative={combineRefAlternative}
252
258
  />
253
- );
254
- });
255
- const buttonClassNames = classnames(
256
- classButton,
257
- styles.buttonDetails,
258
- { [styles.isAlternativeButton]: typeAlternative }
259
- );
260
-
261
- const offerBtnVariantCondition = vehicleComponentName === 'recently' ||
262
- vehicleComponentName === 'landing' ||
263
- vehicleComponentName === 'main' ? 'outlined' : 'contained';
264
- return (
265
- <section className={vehiclePriceSectionClassName}>
266
- {vehicleComponentName === 'favorite' && showCompareCheckboxes && (
267
- <CheckboxMaterial
268
- checked={toCompare}
269
- onChange={toggleCarToCompare}
270
- labelPlacement='start'
271
- label={t('FavoritesPage:toCompare')}
272
- formControlClassName={styles.wrapCheckbox}
273
- />
274
- )}
275
- {vehicleComponentName !== 'favorite' && vehicleComponentName !== 'search' && !isMobileOnly && (
276
- <span className={vehiclePriceTitleClassName}>{t('vehicleProps:title.monthlyFrom')}</span>
277
- )}
278
- {isMobileOnly && !showCompareCheckboxes && (
279
- <span className={vehiclePriceTitleClassName}>{t('vehicleProps:title.monthlyFrom')}</span>
280
- )}
281
- {ListPrices}
282
- {vehicleComponentName === 'favorite' && showCompareCheckboxes && (
283
- <div className={styles.wrapHandleCompare}>
284
- <Button variant='outlined' onClick={onRemoveClick} className={styles.btnCompareRemove} color='error'>
285
- <IconSVG className={styles.removeIcon} name='trashRed' customDimensions />
286
- </Button>
287
- <Button className={styles.btnCarToCompare} variant='outlined' onClick={toggleCarToCompare}>
288
- <span className={styles.btnPlusIcon}>{!toCompare ? '+' : '-'}</span>
289
- {t('FavoritesPage:compare')}
290
- </Button>
291
- </div>
292
- )}
293
- {isDealerSuperAdmin && !typeAlternative ? (
294
- <Button className={styles.addOfferButton} onClick={this.onAddOfferClick}>
295
- {t('vehicleProps:title.addOfferToMainSlide')}
259
+ ))}
260
+ {vehicleComponentName === 'favorite' && showCompareCheckboxes && (
261
+ <div className={styles.wrapHandleCompare}>
262
+ <Button variant='outlined' onClick={onRemoveClick} className={styles.btnCompareRemove} color='error'>
263
+ <IconSVG className={styles.removeIcon} name='trashRed' customDimensions />
296
264
  </Button>
297
- ) : null}
298
- {showOfferBtn ? (
299
- <Button variant={offerBtnVariantCondition} className={buttonClassNames} onClick={this.onDetailsClick}>{t('vehicleProps:title.toOffer')}</Button>
300
- ) : ''}
301
- </section>
302
- );
303
- }
304
- }
305
- export default VehiclePrice;
265
+ <Button className={styles.btnCarToCompare} variant='outlined' onClick={toggleCarToCompare}>
266
+ <span className={styles.btnPlusIcon}>{!toCompare ? '+' : '-'}</span>
267
+ {t('FavoritesPage:compare')}
268
+ </Button>
269
+ </div>
270
+ )}
271
+ {isDealerSuperAdmin && !typeAlternative ? (
272
+ <Button className={styles.addOfferButton} onClick={onAddOfferClick}>
273
+ {t('vehicleProps:title.addOfferToMainSlide')}
274
+ </Button>
275
+ ) : null}
276
+ {showOfferBtn ? (
277
+ <Button variant={offerBtnVariantCondition} className={buttonClassNames} onClick={onDetailsClick}>{t('vehicleProps:title.toOffer')}</Button>
278
+ ) : ''}
279
+ </section>
280
+ );
281
+ };
282
+
283
+ export default VehiclePrice;
@@ -55,6 +55,8 @@ interface IVehicleSmallCardProps {
55
55
  seoText?: string;
56
56
  classButton?: string;
57
57
  mainImageId?: string;
58
+ target?: string;
59
+ rel?: string;
58
60
  crawledAt?: string;
59
61
  modificationDate?: string;
60
62
  baseUrl?: string;
@@ -62,7 +64,6 @@ interface IVehicleSmallCardProps {
62
64
  priceSubMtl?: string | null;
63
65
  ownerName?: string;
64
66
  className?: string;
65
- percentage?: number;
66
67
  id?: string;
67
68
  linkTag?: string;
68
69
  src?: string;
@@ -136,7 +137,6 @@ const VehicleSmallCard: FunctionComponent<IVehicleSmallCardProps> = (props) => {
136
137
  children,
137
138
  iconName,
138
139
  showSlider,
139
- percentage,
140
140
  classButton,
141
141
  hasInteriorExteriorPhoto,
142
142
  dashboardButtonText,
@@ -180,12 +180,12 @@ const VehicleSmallCard: FunctionComponent<IVehicleSmallCardProps> = (props) => {
180
180
  ...slider,
181
181
  price,
182
182
  showNewLabel,
183
- percentage,
184
183
  CircularProgressbar,
185
184
  isReferenceSearch,
186
185
  isAlternative,
187
186
  typeAlternative
188
187
  };
188
+
189
189
  const favoriteProps = {
190
190
  ...title,
191
191
  id,
@@ -276,77 +276,79 @@ const VehicleSmallCard: FunctionComponent<IVehicleSmallCardProps> = (props) => {
276
276
  vehicleComponentName === 'recently';
277
277
  return (
278
278
  <section className={wrapperClassName} onClick={onContainerClick} id={id}>
279
- {createElement(linkTag, {
280
- children: <VehicleTitle {...favoriteProps} />,
281
- ...routeObj,
282
- target,
283
- rel,
284
- className: `${styles.redirectClassLink} ${styles.gridAreaTitle}`,
285
- onClick: () => localStorage.setItem('activeTabCDP', t('vehicleProps:title.financing')),
286
- href: url
287
- })}
279
+ <>
280
+ {createElement(linkTag, {
281
+ children: <VehicleTitle {...favoriteProps} />,
282
+ ...routeObj,
283
+ target,
284
+ rel,
285
+ className: `${styles.redirectClassLink} ${styles.gridAreaTitle}`,
286
+ onClick: () => localStorage.setItem('activeTabCDP', t('vehicleProps:title.financing')),
287
+ href: url
288
+ })}
288
289
 
289
- {createElement(linkTag, {
290
- children: (
291
- <>
292
- {showSlider ? (
293
- <>
294
- {showComponentLikeSlider ? (
295
- <>
296
- <DecoratedSliderForSRL {...decoratedSliderProps} />
297
- {renderIDInfo && isDealer ? renderIDInfo() : null}
298
- {combineRefAlternative && (
299
- <div className={styles.wrapAlternativeData}>
300
- <div>
301
- {offerSource || ownerName ? (
302
- <>
303
- <IconSVG className={styles.svgIcon} name='linkAlternative' />
304
- <span onClick={(e: MouseEvent<HTMLImageElement>) => linkBaseUrl(e)}>
305
- {!typeAlternative ? ownerName : t(`cbd:${offerSource}`)}
290
+ {createElement(linkTag, {
291
+ children: (
292
+ <>
293
+ {showSlider ? (
294
+ <>
295
+ {showComponentLikeSlider ? (
296
+ <>
297
+ <DecoratedSliderForSRL {...decoratedSliderProps} />
298
+ {renderIDInfo && isDealer ? renderIDInfo() : null}
299
+ {combineRefAlternative && (
300
+ <div className={styles.wrapAlternativeData}>
301
+ <div>
302
+ {offerSource || ownerName ? (
303
+ <>
304
+ <IconSVG className={styles.svgIcon} name='linkAlternative' />
305
+ <span onClick={(e: MouseEvent<HTMLImageElement>) => linkBaseUrl(e)}>
306
+ {!typeAlternative ? ownerName : t(`cbd:${offerSource}`)}
307
+ </span>
308
+ </>
309
+ ) : ''}
310
+ </div>
311
+ {crawledAt || modificationDate ? (
312
+ <div>
313
+ <IconSVG className={styles.svgIcon} name='lastCrawledAt' />
314
+ <span>
315
+ {!typeAlternative ? modificationDate : crawledAt}
306
316
  </span>
307
- </>
317
+ </div>
308
318
  ) : ''}
309
319
  </div>
310
- {crawledAt || modificationDate ? (
311
- <div>
312
- <IconSVG className={styles.svgIcon} name='lastCrawledAt' />
313
- <span>
314
- {!typeAlternative ? modificationDate : crawledAt}
315
- </span>
316
- </div>
317
- ) : ''}
318
- </div>
319
- )}
320
- </>
321
- ) : (
322
- <figure className={styles.figure}>
323
- <DecoratedSlider {...decoratedSliderProps} />
324
- </figure>
325
- )}
326
- </>
327
- ) : (
328
- <LazyLoad {...lazyLoadProps}>
329
- <ImageWithStats {...imageProps} {...statsProps} />
330
- </LazyLoad>
331
- )}
332
- </>
333
- ),
334
- ...routeObj,
335
- target,
336
- rel,
337
- className: `${styles.redirectClassLink} ${styles.gridAreaImage}`,
338
- onClick: () => localStorage.setItem('activeTabCDP', t('vehicleProps:title.financing')),
339
- href: url
340
- })}
341
- <VehicleInfo {...vehicleInfoProps} />
342
- <VehiclePrice {...vehiclePriceProps} />
343
- {seoText ? (
344
- <a className={`${styles.redirectClassLink} ${styles.gridAreaSeoText}`} href={url}>
345
- <SeoText seoText={seoText} />
346
- </a>
347
- ) : null
348
- }
349
- {children}
320
+ )}
321
+ </>
322
+ ) : (
323
+ <figure className={styles.figure}>
324
+ <DecoratedSlider {...decoratedSliderProps} />
325
+ </figure>
326
+ )}
327
+ </>
328
+ ) : (
329
+ <LazyLoad {...lazyLoadProps}>
330
+ <ImageWithStats {...imageProps} {...statsProps} />
331
+ </LazyLoad>
332
+ )}
333
+ </>
334
+ ),
335
+ ...routeObj,
336
+ target,
337
+ rel,
338
+ className: `${styles.redirectClassLink} ${styles.gridAreaImage}`,
339
+ onClick: () => localStorage.setItem('activeTabCDP', t('vehicleProps:title.financing')),
340
+ href: url
341
+ })}
342
+ <VehicleInfo {...vehicleInfoProps} />
343
+ <VehiclePrice {...vehiclePriceProps} />
344
+ {seoText ? (
345
+ <a className={`${styles.redirectClassLink} ${styles.gridAreaSeoText}`} href={url}>
346
+ <SeoText seoText={seoText} />
347
+ </a>
348
+ ) : null
349
+ }
350
+ {children}
351
+ </>
350
352
  </section>
351
353
  );
352
354
  };
@@ -364,6 +366,7 @@ VehicleSmallCard.defaultProps = {
364
366
  info: {},
365
367
  crawledAt: 'N/A',
366
368
  baseUrl: '',
369
+ typeAlternative: '',
367
370
  offerSource: '',
368
371
  src: 'https://images.auto.de/noimage/small',
369
372
  environmentEmissions: null,
@@ -11,61 +11,53 @@ import { preloadNearbyImages } from '../../../framework/utils/CommonUtils';
11
11
  import { IVehicleSliderForSRLProps } from '../../../framework/types/types';
12
12
  import styles from './VehicleSlider.styl';
13
13
 
14
- interface IVehicleSliderForSRLState {
15
- noImagesLoaded: boolean;
16
- activeSlide: number;
17
- }
18
14
 
19
- const SlickButtonFix: React.FunctionComponent = ({ currentSlide, slideCount, children, ...props }: any) => (
15
+ const SlickButtonFix: React.FC = ({ currentSlide, slideCount, children, ...props }: any) => (
20
16
  <div {...props} tabIndex={-1}>{children}</div>
21
17
  );
22
18
 
23
- class VehicleSliderForSRL extends React.Component<IVehicleSliderForSRLProps, IVehicleSliderForSRLState> {
24
- readonly state = {
25
- noImagesLoaded: false,
26
- activeSlide: 0
27
- };
28
-
29
- static readonly defaultProps: IVehicleSliderForSRLProps = {
30
- mainImageId: '',
31
- imagesCount: 0,
32
- imageSize: 'small',
33
- isAlternative: false,
34
- typeAlternative: '',
35
- images: [],
36
- getCarImagesData: () => null
37
- };
38
-
39
- beforeChange = () => {
40
- const { carId, images, getCarImagesData, type, typeAlternative } = this.props;
41
- const { activeSlide } = this.state;
19
+ const VehicleSliderForSRL: React.FC<IVehicleSliderForSRLProps> = ({
20
+ id,
21
+ src,
22
+ className,
23
+ images,
24
+ imagesCount,
25
+ imageSize,
26
+ mainImageId,
27
+ getCarImagesData,
28
+ type,
29
+ isAlternative,
30
+ typeAlternative,
31
+ isReferenceSearch,
32
+ CircularProgressbar,
33
+ onSlideChange
34
+ }: IVehicleSliderForSRLProps) => {
35
+ const [ noImagesLoaded, setNoImagesLoaded ] = React.useState<boolean>(false);
36
+ const [ activeSlide, setActiveSlide ] = React.useState<number>(0);
37
+
38
+ const beforeChange = () => {
42
39
 
43
40
  const isMyVehicle: boolean = type === 'myVehicle';
44
41
 
45
42
  if (_isLength(images)) return false;
46
- getCarImagesData(carId, true, isMyVehicle, type, typeAlternative).then((data) => {
43
+ getCarImagesData(id, true, isMyVehicle, type, typeAlternative).then((data) => {
47
44
  // a case when all images are in_postprocessing
48
45
 
49
46
  if (!data || data.length === 0) {
50
- this.setState({ noImagesLoaded: true });
47
+ setNoImagesLoaded(true);
51
48
  }
52
49
 
53
50
  preloadNearbyImages(data, activeSlide, 'imageUrlSmall');
54
51
  });
55
52
  };
56
53
 
57
- onSlideChange = (index: number): void => {
58
- const { images } = this.props;
59
-
60
- this.setState({ activeSlide: index });
61
-
62
- this.props.onSlideChange(index);
54
+ const onHandleSlideChange = (index: number): void => {
55
+ setActiveSlide(index);
56
+ onSlideChange(index);
63
57
  preloadNearbyImages(images, index, 'imageUrlSmall');
64
58
  };
65
59
 
66
- renderSliderImages = () => {
67
- const { carId, mainImageId, images, imagesCount, imageSize, src, isAlternative } = this.props;
68
- const { activeSlide } = this.state;
60
+ const renderSliderImages = () => {
69
61
 
70
62
  const imageProps = {
71
63
  isAlternative,
@@ -106,11 +98,11 @@ class VehicleSliderForSRL extends React.Component<IVehicleSliderForSRLProps, IVe
106
98
 
107
99
  if (mainImageId && !!imagesCount) {
108
100
  const mainImage = (
109
- <LazyLoad {...lazyLoadProps} key={carId}>
101
+ <LazyLoad {...lazyLoadProps} key={id}>
110
102
  <Image src={src} {...imageProps} />
111
103
  </LazyLoad>
112
104
  );
113
- const spinner = !this.state.noImagesLoaded ? (
105
+ const spinner = !noImagesLoaded ? (
114
106
  <div className={styles.spinnerWrap} key='spinnerWrap'>
115
107
  <Loader className={styles.spinner} size='medium' key='small_slider_loader' />
116
108
  </div>
@@ -121,18 +113,18 @@ class VehicleSliderForSRL extends React.Component<IVehicleSliderForSRLProps, IVe
121
113
 
122
114
  return (
123
115
  <LazyLoad {...lazyLoadProps}>
124
- <Image src={`${PLACEHOLDER_IMAGE}${imageSize}`} key={carId} {...imageProps} />
116
+ <Image src={`${PLACEHOLDER_IMAGE}${imageSize}`} key={id} {...imageProps} />
125
117
  </LazyLoad>
126
118
  );
127
119
  };
128
120
 
129
- renderSlider = () => {
121
+ const renderSlider = () => {
130
122
  const settings = {
123
+ beforeChange,
131
124
  autoPlay: false,
132
125
  speed: 300,
133
126
  infinite: true,
134
127
  dots: false,
135
- beforeChange: this.beforeChange,
136
128
  className: styles.slider,
137
129
  accessibility: false,
138
130
  draggable: true,
@@ -140,31 +132,37 @@ class VehicleSliderForSRL extends React.Component<IVehicleSliderForSRLProps, IVe
140
132
  prevArrow: <SlickButtonFix />,
141
133
  swipeToSlide: true,
142
134
  focusOnSelect: true,
143
- afterChange: this.onSlideChange,
144
- key: `${this.state.noImagesLoaded}`
135
+ afterChange: onHandleSlideChange,
136
+ key: `${noImagesLoaded}`
145
137
  };
146
138
 
147
139
  return (
148
- <div className={styles.wrapper} onMouseEnter={this.beforeChange}>
149
- <Slider {...settings}>{this.renderSliderImages()}</Slider>
140
+ <div className={styles.wrapper} onMouseEnter={beforeChange}>
141
+ <Slider {...settings}>{renderSliderImages()}</Slider>
150
142
  </div>
151
143
  );
152
144
  };
153
145
 
154
- render(): JSX.Element {
155
- const { images, className, type, isReferenceSearch, CircularProgressbar } = this.props;
156
-
157
- const containerClassName = classnames(styles.imageContainer, className, {
158
- [styles[type]]: !!type
159
- });
160
-
161
- return (
162
- <div className={containerClassName}>
163
- {isReferenceSearch && <CircularProgressbar />}
164
- {images ? this.renderSlider() : false}
165
- </div>
166
- );
167
- }
146
+ const containerClassName = classnames(styles.imageContainer, className, {
147
+ [styles[type]]: !!type
148
+ });
149
+
150
+ return (
151
+ <div className={containerClassName}>
152
+ {isReferenceSearch && <CircularProgressbar />}
153
+ {images ? renderSlider() : false}
154
+ </div>
155
+ );
156
+ };
157
+
158
+ VehicleSliderForSRL.defaultProps = {
159
+ mainImageId: '',
160
+ imagesCount: 0,
161
+ imageSize: 'small',
162
+ isAlternative: false,
163
+ typeAlternative: '',
164
+ images: [],
165
+ getCarImagesData: () => null
168
166
  }
169
167
 
170
168
  export default VehicleSliderForSRL;
@@ -32,154 +32,148 @@ export interface IStatsWrapperProps {
32
32
  imagesCount?: number;
33
33
  showNewLabel?: boolean;
34
34
  onFavoriteClick?: (event: any) => void;
35
-
35
+ getCarImagesData?: (carId: string, force?: boolean, includeAll?: boolean, type?: any, typeAlternative?: string) => Promise<any>;
36
36
  [key: string]: any;
37
37
  }
38
38
 
39
- export interface IStatsWrapperState {
40
- activeSlide: number;
41
- }
42
-
43
- const MIN_PERCENT = 5;
44
- const MIN_PRICE_DIFFERENCE = 500;
45
-
46
- export default function withStats(WrappedComponent: any) {
47
- return class extends React.Component<IStatsWrapperProps, IStatsWrapperState> {
48
- static defaultProps = {
49
- classWrapPrice: '',
50
- statsSize: 'xs',
51
- showNewLabel: false,
52
- price: {
53
- historyPriceDifference: 0,
54
- historyPriceDifferencePerCent: 0
55
- }
56
- };
57
-
58
- state = {
59
- activeSlide: 0
60
- };
61
-
62
- onSlideChange = (activeSlide: number) => {
63
- this.setState(() => ({ activeSlide }));
64
-
65
- if (typeof this.props.onSlideChange === 'function') {
66
- this.props.onSlideChange(activeSlide);
67
- }
68
- };
69
-
70
- renderImagesData = (): JSX.Element => {
71
- const { imagesCount, statsSize } = this.props;
72
- if (!Number.isFinite(imagesCount)) return null;
73
-
74
- const { activeSlide } = this.state;
75
- const delimiters = { xs: '|', sm: '|', md: 'von' };
76
-
77
- return (
78
- <div className={styles.section}>
79
- {statsSize === 'md' ? <IconSVG name='common_camera' customDimensions className={styles.cameraIcon} /> : null}
80
- {!!imagesCount && <span>{`${activeSlide + 1} ${delimiters[statsSize]} ${imagesCount}`}</span>}
81
- </div>
82
- );
83
- };
84
-
85
- renderRotateSvg = (): JSX.Element => {
86
- const { hasInteriorExteriorPhoto, images } = this.props;
87
- const hasExteriorPhotos = hasInteriorExteriorPhoto && Array.isArray(images) && images.length > 0;
88
- if (!hasExteriorPhotos) return null;
89
- return (
90
- <div className={styles.section}>
91
- {hasExteriorPhotos ? (
92
- <IconSVG name='rotate360New' customDimensions className={styles.statsEyeIcon} />
93
- ) : null}
94
- </div>
95
- );
96
- };
97
-
98
- renderStarButton = () => {
99
- const { isFavoured, onFavoriteClick } = this.props;
100
- if (!onFavoriteClick) return null;
101
-
102
- return (
103
- <IconSVG
104
- name='common_StarRoundedCorners'
105
- customDimensions
106
- className={classnames(styles.starButton, { [styles.starButtonFavored]: isFavoured })}
107
- onClick={onFavoriteClick}
108
- />
109
- );
110
- };
111
-
112
- renderStatsData = (): JSX.Element => {
113
- const { statsData, isFavoured, onFavoriteClick } = this.props;
114
- if (!statsData) return null;
115
- const { totalCarImpCount, totalFavCount } = statsData;
116
- const favoritesClassName = classnames(
117
- styles.statsFavoritesCount,
118
- {
119
- [styles.accented]: isFavoured,
120
- [styles.clickable]: typeof onFavoriteClick === 'function'
121
- });
122
- const favoritesIconClassName = classnames(styles.statsStarIcon, { [styles.accented]: isFavoured });
123
-
124
- return (
125
- <div className={styles.section}>
126
- {!!totalCarImpCount ? <div className={styles.statsViewsCount}>
127
- <IconSVG name='common_SliderEye' customDimensions className={styles.statsEyeIcon} />
128
- <span>
129
- {totalCarImpCount}
130
- </span>
131
- </div> : null}
132
- {!!totalFavCount ? <div className={favoritesClassName} onClick={onFavoriteClick}>
133
- <IconSVG name='star' customDimensions className={favoritesIconClassName} />
134
- <span>
135
- {totalFavCount}
136
- </span>
137
- </div> : null}
138
- </div>
139
- );
140
- };
141
-
142
- renderPriceData = () => {
143
- const { price: { historyPriceDifference, historyPriceDifferencePerCent }, showNewLabel, classWrapPrice, t } = this.props;
144
-
145
- const newText = !!t ? t('vehicleProps:promoSlider.new') : 'neu';
146
- const EUR = `\u20AC`;
147
-
148
- return (
149
- <div className={classnames(styles.topWrapper, classWrapPrice)}>
150
- {showNewLabel && <Badge type='blue' className={styles.new}>{newText}</Badge>}
151
- {!!historyPriceDifference && historyPriceDifference >= MIN_PRICE_DIFFERENCE && (
152
- <Badge type='green'>
153
- {`-`}
154
- <FormattedNumber value={historyPriceDifference} numbersAfterDot={0} />
155
- {` ${EUR}`}
156
- </Badge>
157
- )}
158
- {!!historyPriceDifferencePerCent && historyPriceDifferencePerCent >= MIN_PERCENT && (
159
- <Badge type='red' className={styles.priceDifferencePerCent}>-{historyPriceDifferencePerCent}%</Badge>
160
- )}
161
- </div>
162
- );
163
- };
164
-
165
- render() {
166
- const {
167
- statsSize, isFavoured, onFavoriteClick, statsData, isReferenceSearch,
168
- ...wrappedComponentProps
169
- } = this.props;
170
-
171
- return (
172
- <div className={styles.wrapper}>
173
- {!isReferenceSearch && this.renderPriceData()}
174
- <WrappedComponent {...wrappedComponentProps} onSlideChange={this.onSlideChange} isReferenceSearch={isReferenceSearch} />
175
- <div className={classnames(styles.controls, styles[statsSize])}>
176
- {this.renderImagesData()}
177
- {this.renderRotateSvg()}
178
- {this.renderStarButton()}
179
- {this.renderStatsData()}
180
- </div>
181
- </div>
182
- );
39
+ const withStats = (WrappedComponent: any) => ({
40
+ t,
41
+ images,
42
+ hasInteriorExteriorPhoto,
43
+ imagesCount,
44
+ statsData,
45
+ isFavoured,
46
+ onFavoriteClick,
47
+ isReferenceSearch,
48
+ onSlideChange,
49
+ classWrapPrice = '',
50
+ showNewLabel = false,
51
+ statsSize = 'xs',
52
+ price: { historyPriceDifference = 0, historyPriceDifferencePerCent = 0 },
53
+ ...props
54
+ }: IStatsWrapperProps) => {
55
+ const [ activeSlide, setActiveSlide ] = React.useState<number>(0);
56
+
57
+ const MIN_PERCENT = 5;
58
+ const MIN_PRICE_DIFFERENCE = 500;
59
+
60
+ const onHandleSlideChange = (activeSlide: number) => {
61
+ setActiveSlide(activeSlide);
62
+
63
+ if (typeof onSlideChange === 'function') {
64
+ onSlideChange(activeSlide);
183
65
  }
184
66
  };
185
- }
67
+
68
+ const renderImagesData = (): JSX.Element => {
69
+ if (!Number.isFinite(imagesCount)) return null;
70
+
71
+ const delimiters = { xs: '|', sm: '|', md: 'von' };
72
+
73
+ return (
74
+ <div className={styles.section}>
75
+ {statsSize === 'md' ? <IconSVG name='common_camera' customDimensions className={styles.cameraIcon} /> : null}
76
+ {!!imagesCount && <span>{`${activeSlide + 1} ${delimiters[statsSize]} ${imagesCount}`}</span>}
77
+ </div>
78
+ );
79
+ };
80
+
81
+ const renderRotateSvg = (): JSX.Element => {
82
+ const hasExteriorPhotos = hasInteriorExteriorPhoto && Array.isArray(images) && images.length > 0;
83
+ if (!hasExteriorPhotos) return null;
84
+ return (
85
+ <div className={styles.section}>
86
+ {hasExteriorPhotos ? (
87
+ <IconSVG name='rotate360New' customDimensions className={styles.statsEyeIcon} />
88
+ ) : null}
89
+ </div>
90
+ );
91
+ };
92
+
93
+ const renderStarButton = () => {
94
+ if (!onFavoriteClick) return null;
95
+
96
+ return (
97
+ <IconSVG
98
+ name='common_StarRoundedCorners'
99
+ customDimensions
100
+ className={classnames(styles.starButton, { [styles.starButtonFavored]: isFavoured })}
101
+ onClick={onFavoriteClick}
102
+ />
103
+ );
104
+ };
105
+
106
+ const renderStatsData = (): JSX.Element => {
107
+ if (!statsData) return null;
108
+ const { totalCarImpCount, totalFavCount } = statsData;
109
+ const favoritesClassName = classnames(
110
+ styles.statsFavoritesCount,
111
+ {
112
+ [styles.accented]: isFavoured,
113
+ [styles.clickable]: typeof onFavoriteClick === 'function'
114
+ });
115
+ const favoritesIconClassName = classnames(styles.statsStarIcon, { [styles.accented]: isFavoured });
116
+
117
+ return (
118
+ <div className={styles.section}>
119
+ {!!totalCarImpCount ? <div className={styles.statsViewsCount}>
120
+ <IconSVG name='common_SliderEye' customDimensions className={styles.statsEyeIcon} />
121
+ <span>
122
+ {totalCarImpCount}
123
+ </span>
124
+ </div> : null}
125
+ {!!totalFavCount ? <div className={favoritesClassName} onClick={onFavoriteClick}>
126
+ <IconSVG name='star' customDimensions className={favoritesIconClassName} />
127
+ <span>
128
+ {totalFavCount}
129
+ </span>
130
+ </div> : null}
131
+ </div>
132
+ );
133
+ };
134
+
135
+ const renderPriceData = () => {
136
+ const newText = !!t ? t('vehicleProps:promoSlider.new') : 'neu';
137
+ const EUR = `\u20AC`;
138
+
139
+ return (
140
+ <div className={classnames(styles.topWrapper, classWrapPrice)}>
141
+ {showNewLabel && <Badge type='blue' className={styles.new}>{newText}</Badge>}
142
+ {!!historyPriceDifference && historyPriceDifference >= MIN_PRICE_DIFFERENCE && (
143
+ <Badge type='green'>
144
+ {`-`}
145
+ <FormattedNumber value={historyPriceDifference} numbersAfterDot={0} />
146
+ {` ${EUR}`}
147
+ </Badge>
148
+ )}
149
+ {!!historyPriceDifferencePerCent && historyPriceDifferencePerCent >= MIN_PERCENT && (
150
+ <Badge type='red' className={styles.priceDifferencePerCent}>-{historyPriceDifferencePerCent}%</Badge>
151
+ )}
152
+ </div>
153
+ );
154
+ };
155
+
156
+ const wrappedComponentProps = {
157
+ t,
158
+ images,
159
+ hasInteriorExteriorPhoto,
160
+ imagesCount,
161
+ classWrapPrice,
162
+ ...props
163
+ }
164
+
165
+ return (
166
+ <div className={styles.wrapper}>
167
+ {!isReferenceSearch && renderPriceData()}
168
+ <WrappedComponent onSlideChange={onHandleSlideChange} isReferenceSearch={isReferenceSearch} {...wrappedComponentProps} />
169
+ <div className={classnames(styles.controls, styles[statsSize])}>
170
+ {renderImagesData()}
171
+ {renderRotateSvg()}
172
+ {renderStarButton()}
173
+ {renderStatsData()}
174
+ </div>
175
+ </div>
176
+ );
177
+ };
178
+
179
+ export default withStats;
@@ -141,8 +141,10 @@ export interface IVehicleSliderProps extends Settings {
141
141
  }
142
142
 
143
143
  export interface IVehicleSliderForSRLProps {
144
- carId?: string;
144
+ t?: (key: string, options?: object) => string;
145
+ id?: string;
145
146
  mainImageId?: string;
147
+ hasInteriorExteriorPhoto?: boolean;
146
148
  imageSize?: 'small' | 'medium' | 'large';
147
149
  imagesCount?: number;
148
150
  images?: ICarImage[];
@@ -688,7 +688,7 @@ const getDecoratedProps = (
688
688
  ? t('vehicleProps:value.co2Combined', { co2: co2.toLocaleString(language) })
689
689
  : t('vehicleProps:value.na');
690
690
 
691
- return <>{consumptionValue} <br /> {co2Value}</>;
691
+ return <>{wrapValue(consumptionValue)} <br /> {wrapValue(co2Value)}</>;
692
692
  }
693
693
  },
694
694
  consumptionPowerCombinedAlternateView: {
@@ -708,7 +708,7 @@ const getDecoratedProps = (
708
708
  ? t('vehicleProps:value.co2Combined', { co2: co2.toLocaleString(language) })
709
709
  : t('vehicleProps:value.na');
710
710
 
711
- return <>{consumptionValue} <br /> {co2Value}</>;
711
+ return <>{wrapValue(consumptionValue)} <br /> {wrapValue(co2Value)}</>;
712
712
  }
713
713
  },
714
714
  consumptionHydrogenCombinedAlternateView: {
@@ -728,7 +728,7 @@ const getDecoratedProps = (
728
728
  ? t('vehicleProps:value.co2Combined', { co2: co2.toLocaleString(language) })
729
729
  : t('vehicleProps:value.na');
730
730
 
731
- return <>{consumptionValue} <br /> {co2Value}</>;
731
+ return <>{wrapValue(consumptionValue)} <br /> {wrapValue(co2Value)}</>;
732
732
  }
733
733
  },
734
734
  consumptionGasCombinedAlternateView: {
@@ -749,7 +749,7 @@ const getDecoratedProps = (
749
749
  ? t('vehicleProps:value.co2Combined', { co2: co2.toLocaleString(language) })
750
750
  : t('vehicleProps:value.na');
751
751
 
752
- return <>{consumptionValue} <br /> {co2Value}</>;
752
+ return <>{wrapValue(consumptionValue)} <br /> {wrapValue(co2Value)}</>;
753
753
  }
754
754
  },
755
755