@bytebrand/fe-ui-core-autobahn 1.0.132 → 1.0.134
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/chrome/Footer.tsx +9 -1
- package/package.json +30 -30
- package/theme/md3.css +47 -0
- package/vdp/VdpModules.tsx +168 -1
- package/vdp/index.ts +7 -0
- package/vdp/types.ts +53 -0
package/chrome/Footer.tsx
CHANGED
|
@@ -79,6 +79,13 @@ export interface FooterProps {
|
|
|
79
79
|
* strings as the legacy footer so /search stays compliant where prices/rates are shown.
|
|
80
80
|
*/
|
|
81
81
|
t: TranslationFunction;
|
|
82
|
+
/**
|
|
83
|
+
* Adds footnotes ⁵ (Pkw-EnVKV possible CO₂ costs) and ⁶ (§3d KraftStG EV tax exemption) to the
|
|
84
|
+
* disclaimer block, right after ⁴ (price evaluation) and before the WLTP consumption note. Real
|
|
85
|
+
* legal copy tied to the "Laufende Kosten pro Jahr" cards on the CDP — only pass true there
|
|
86
|
+
* (VehicleDetailedNextPage), never site-wide, since every other page shows only footnotes 1-4.
|
|
87
|
+
*/
|
|
88
|
+
showCostFootnotes?: boolean;
|
|
82
89
|
}
|
|
83
90
|
|
|
84
91
|
/**
|
|
@@ -86,7 +93,7 @@ export interface FooterProps {
|
|
|
86
93
|
* disclaimer block, and a copyright + "Nach Oben" bar. Pure/presentational MD3 chrome — renders
|
|
87
94
|
* correctly only inside a `<div className="md3">` subtree (scoped theme at source/theme/autobahn).
|
|
88
95
|
*/
|
|
89
|
-
const Footer: React.FunctionComponent<FooterProps> = ({ t }) => {
|
|
96
|
+
const Footer: React.FunctionComponent<FooterProps> = ({ t, showCostFootnotes }) => {
|
|
90
97
|
const scrollTop = (): void => window.scroll({ top: 0, left: 0, behavior: 'smooth' });
|
|
91
98
|
const now = new Date();
|
|
92
99
|
const year = now.getFullYear();
|
|
@@ -179,6 +186,7 @@ const Footer: React.FunctionComponent<FooterProps> = ({ t }) => {
|
|
|
179
186
|
t('footer:manufacturerUvp'),
|
|
180
187
|
t('footer:uvpComparisonRate'),
|
|
181
188
|
t('footer:priceEvaluation', { date: today }),
|
|
189
|
+
...(showCostFootnotes ? [t('footer:co2CostsInfo'), t('footer:evTaxExemption')] : []),
|
|
182
190
|
t('footer:consumptionInfo'),
|
|
183
191
|
t('footer:vehicleImages'),
|
|
184
192
|
].join('<br />'),
|
package/package.json
CHANGED
|
@@ -1,30 +1,30 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "@bytebrand/fe-ui-core-autobahn",
|
|
3
|
-
"version": "1.0.
|
|
4
|
-
"description": "auto.de md3 (Autobahn) design system — UI primitives, cards, chrome, VDP modules, theme CSS and locales. Ships raw TypeScript source (like fe-ui-core before it); each consumer's bundler compiles it.",
|
|
5
|
-
"main": "index.ts",
|
|
6
|
-
"license": "UNLICENSED",
|
|
7
|
-
"peerDependencies": {
|
|
8
|
-
"react": "^18.0.0",
|
|
9
|
-
"react-dom": "^18.0.0"
|
|
10
|
-
},
|
|
11
|
-
"dependencies": {
|
|
12
|
-
"@bytebrand/car-schema-selectors": "^2.0.7",
|
|
13
|
-
"@bytebrand/fe-financing": "^5.14.20",
|
|
14
|
-
"classnames": "2.2.6",
|
|
15
|
-
"clsx": "^2.1.1",
|
|
16
|
-
"d3-format": "1.4.5",
|
|
17
|
-
"js-cookie": "^2.2.0",
|
|
18
|
-
"lodash": "^4.17.21",
|
|
19
|
-
"lucide-react": "^0.288.0",
|
|
20
|
-
"mobx-react": "^7.6.0",
|
|
21
|
-
"moment": "^2.29.1",
|
|
22
|
-
"qs": "^6.6.0",
|
|
23
|
-
"react-device-detect": "^2.1.2",
|
|
24
|
-
"react-grid-system": "^5.0.2",
|
|
25
|
-
"react-lazyload": "^3.2.0",
|
|
26
|
-
"react-scroll": "^1.9.3",
|
|
27
|
-
"react-slick": "^0.29.0",
|
|
28
|
-
"slick-carousel": "1.8.1"
|
|
29
|
-
}
|
|
30
|
-
}
|
|
1
|
+
{
|
|
2
|
+
"name": "@bytebrand/fe-ui-core-autobahn",
|
|
3
|
+
"version": "1.0.134",
|
|
4
|
+
"description": "auto.de md3 (Autobahn) design system — UI primitives, cards, chrome, VDP modules, theme CSS and locales. Ships raw TypeScript source (like fe-ui-core before it); each consumer's bundler compiles it.",
|
|
5
|
+
"main": "index.ts",
|
|
6
|
+
"license": "UNLICENSED",
|
|
7
|
+
"peerDependencies": {
|
|
8
|
+
"react": "^18.0.0",
|
|
9
|
+
"react-dom": "^18.0.0"
|
|
10
|
+
},
|
|
11
|
+
"dependencies": {
|
|
12
|
+
"@bytebrand/car-schema-selectors": "^2.0.7",
|
|
13
|
+
"@bytebrand/fe-financing": "^5.14.20",
|
|
14
|
+
"classnames": "2.2.6",
|
|
15
|
+
"clsx": "^2.1.1",
|
|
16
|
+
"d3-format": "1.4.5",
|
|
17
|
+
"js-cookie": "^2.2.0",
|
|
18
|
+
"lodash": "^4.17.21",
|
|
19
|
+
"lucide-react": "^0.288.0",
|
|
20
|
+
"mobx-react": "^7.6.0",
|
|
21
|
+
"moment": "^2.29.1",
|
|
22
|
+
"qs": "^6.6.0",
|
|
23
|
+
"react-device-detect": "^2.1.2",
|
|
24
|
+
"react-grid-system": "^5.0.2",
|
|
25
|
+
"react-lazyload": "^3.2.0",
|
|
26
|
+
"react-scroll": "^1.9.3",
|
|
27
|
+
"react-slick": "^0.29.0",
|
|
28
|
+
"slick-carousel": "1.8.1"
|
|
29
|
+
}
|
|
30
|
+
}
|
package/theme/md3.css
CHANGED
|
@@ -7581,6 +7581,7 @@ line-height: 31px;
|
|
|
7581
7581
|
display: flex;
|
|
7582
7582
|
gap: 5px;
|
|
7583
7583
|
align-items: flex-end;
|
|
7584
|
+
margin-bottom: 20px;
|
|
7584
7585
|
}
|
|
7585
7586
|
.md3 .co2-col {
|
|
7586
7587
|
flex: 1;
|
|
@@ -11276,3 +11277,49 @@ color: #005CFF;
|
|
|
11276
11277
|
border-bottom-right-radius: 2px;
|
|
11277
11278
|
}
|
|
11278
11279
|
}
|
|
11280
|
+
|
|
11281
|
+
/* VdpEnergyTaxSummary ("Energiekosten und Kraftfahrzeugsteuer pro Jahr" card, VdpModules.tsx)
|
|
11282
|
+
— desktop layout (row, padding: 15px, border-right divider between the 2 columns) is
|
|
11283
|
+
inline JS styles on the component, untouched. padding + the divider are the only two
|
|
11284
|
+
properties that change on mobile, so THOSE (only) live here instead of inline, letting
|
|
11285
|
+
this media query override them without !important. */
|
|
11286
|
+
.md3 .vdp-ets-col {
|
|
11287
|
+
padding: 15px;
|
|
11288
|
+
}
|
|
11289
|
+
.md3 .vdp-ets-col--first {
|
|
11290
|
+
border-right: 1px solid var(--md-outline-variant);
|
|
11291
|
+
}
|
|
11292
|
+
@media (max-width: 600px) {
|
|
11293
|
+
.md3 .vdp-ets-row {
|
|
11294
|
+
flex-direction: column;
|
|
11295
|
+
}
|
|
11296
|
+
.md3 .vdp-ets-col {
|
|
11297
|
+
padding: 14px 16px;
|
|
11298
|
+
}
|
|
11299
|
+
.md3 .vdp-ets-col--first {
|
|
11300
|
+
border-right: none;
|
|
11301
|
+
border-bottom: 1px solid var(--md-outline-variant);
|
|
11302
|
+
}
|
|
11303
|
+
}
|
|
11304
|
+
|
|
11305
|
+
/* VdpCo2CostsSummary ("Mögliche CO₂-Kosten..." card, VdpModules.tsx) — same treatment as
|
|
11306
|
+
.vdp-ets-* above, just 3 columns (low/middle/high) instead of 2; the first two carry the
|
|
11307
|
+
divider, the last one never does (nothing to its right/below). */
|
|
11308
|
+
.md3 .vdp-ccs-col {
|
|
11309
|
+
padding: 15px;
|
|
11310
|
+
}
|
|
11311
|
+
.md3 .vdp-ccs-col--divider {
|
|
11312
|
+
border-right: 1px solid var(--md-outline-variant);
|
|
11313
|
+
}
|
|
11314
|
+
@media (max-width: 600px) {
|
|
11315
|
+
.md3 .vdp-ccs-row {
|
|
11316
|
+
flex-direction: column;
|
|
11317
|
+
}
|
|
11318
|
+
.md3 .vdp-ccs-col {
|
|
11319
|
+
padding: 14px 16px;
|
|
11320
|
+
}
|
|
11321
|
+
.md3 .vdp-ccs-col--divider {
|
|
11322
|
+
border-right: none;
|
|
11323
|
+
border-bottom: 1px solid var(--md-outline-variant);
|
|
11324
|
+
}
|
|
11325
|
+
}
|
package/vdp/VdpModules.tsx
CHANGED
|
@@ -26,7 +26,7 @@ import { TranslationFunction } from '../types';
|
|
|
26
26
|
|
|
27
27
|
import { Button, Dropdown, DropdownOption, Icon, Spec, StatChip, Stars } from '../ui';
|
|
28
28
|
import { CO2_CLASSES, CO2_COLORS, TIER_LABELS, TIER_KEYS, TIER_COLORS, TIER_BACKGROUNDS } from '../constants';
|
|
29
|
-
import { defaultVdpSpecs, EquipmentGroups, PriceRatingBands, VehicleDetail, VdpSpec, VdpReview } from './types';
|
|
29
|
+
import { defaultVdpSpecs, EquipmentGroups, PriceRatingBands, VehicleDetail, VdpSpec, VdpReview, RunningCostRow, EnergyTaxSummary } from './types';
|
|
30
30
|
import { AddServicesTooltipBody, CalcRow, DocCheckIcon, EvalBar, expanderBtnStyle, FinanceMode, Slider, TermChips, ToggleRow } from './FinanceCalculator';
|
|
31
31
|
import { formatEur as eur, formatEurCents as eurCents, formatPct as pct } from '../utils/financeFormat';
|
|
32
32
|
|
|
@@ -364,6 +364,160 @@ export const VdpSpecTable: React.FunctionComponent<VdpSpecTableProps> = ({ vehic
|
|
|
364
364
|
);
|
|
365
365
|
};
|
|
366
366
|
|
|
367
|
+
// ---------------------------------------------------------------------------
|
|
368
|
+
// "Energiekosten und Kraftfahrzeugsteuer pro Jahr" summary card — new Figma design.
|
|
369
|
+
// Deliberately its OWN literal inline styles straight from the Figma spec (hex colors,
|
|
370
|
+
// 'Arimo', exact px) rather than the shared mcard/Spec/md-headline-sm grammar — this frame
|
|
371
|
+
// is a one-off design, not part of the .md3 token system. Covers petrol/diesel, BEV, and
|
|
372
|
+
// PHEV (fuel-type-branching data built by toVehicleDetail.ts) — this replaced the legacy-
|
|
373
|
+
// parity "Laufende Kosten pro Jahr" card (formerly VdpRunningCosts here), which showed the
|
|
374
|
+
// SAME figures via the old accordion.tableCostsPerYear layout/wording and has been removed
|
|
375
|
+
// now that this card covers every fuel type; keeping both would show the same numbers
|
|
376
|
+
// twice with inconsistent wording (e.g. old block's "0,00 EUR/Jahr" Kfz-Steuer vs. this
|
|
377
|
+
// card's real "befristet steuerbefreit" text for a BEV).
|
|
378
|
+
// ---------------------------------------------------------------------------
|
|
379
|
+
|
|
380
|
+
export interface VdpEnergyTaxSummaryProps {
|
|
381
|
+
vehicle: VehicleDetail;
|
|
382
|
+
t: TranslationFunction;
|
|
383
|
+
}
|
|
384
|
+
|
|
385
|
+
const energyTaxLabelStyle: React.CSSProperties = {
|
|
386
|
+
fontFamily: 'Arimo',
|
|
387
|
+
fontStyle: 'normal',
|
|
388
|
+
fontWeight: 400,
|
|
389
|
+
fontSize: 13,
|
|
390
|
+
lineHeight: '18px',
|
|
391
|
+
color: '#5B6B7F',
|
|
392
|
+
};
|
|
393
|
+
|
|
394
|
+
const energyTaxValueStyle: React.CSSProperties = {
|
|
395
|
+
fontFamily: 'Arimo',
|
|
396
|
+
fontStyle: 'normal',
|
|
397
|
+
fontWeight: 700,
|
|
398
|
+
fontSize: 18,
|
|
399
|
+
lineHeight: '24px',
|
|
400
|
+
color: '#0E2238',
|
|
401
|
+
};
|
|
402
|
+
|
|
403
|
+
const energyTaxNoteStyle: React.CSSProperties = {
|
|
404
|
+
fontFamily: 'Arimo',
|
|
405
|
+
fontStyle: 'normal',
|
|
406
|
+
fontWeight: 400,
|
|
407
|
+
fontSize: 11,
|
|
408
|
+
lineHeight: '15px',
|
|
409
|
+
color: '#5B6B7F',
|
|
410
|
+
};
|
|
411
|
+
|
|
412
|
+
// Shared by both new-Figma-design cards below (VdpEnergyTaxSummary + VdpCo2CostsSummary) —
|
|
413
|
+
// the "⁵"/"⁶" superscript footnote markers, and the h2 title.
|
|
414
|
+
const footnoteStyle: React.CSSProperties = {
|
|
415
|
+
fontFamily: 'Arimo',
|
|
416
|
+
fontStyle: 'normal',
|
|
417
|
+
fontWeight: 700,
|
|
418
|
+
fontSize: 18,
|
|
419
|
+
lineHeight: '24px',
|
|
420
|
+
color: '#0E2238',
|
|
421
|
+
};
|
|
422
|
+
|
|
423
|
+
const summaryCardTitleStyle: React.CSSProperties = {
|
|
424
|
+
// <h2> carries a UA-stylesheet default margin (top + bottom) unless reset — zero it
|
|
425
|
+
// explicitly so ONLY marginBottom: 10 (the spec'd value) applies, no stray top padding/gap.
|
|
426
|
+
margin: 0,
|
|
427
|
+
marginBottom: 10,
|
|
428
|
+
fontFamily: 'Arimo',
|
|
429
|
+
fontStyle: 'normal',
|
|
430
|
+
fontWeight: 700,
|
|
431
|
+
fontSize: 15,
|
|
432
|
+
lineHeight: '20px',
|
|
433
|
+
color: '#0E2238',
|
|
434
|
+
};
|
|
435
|
+
|
|
436
|
+
export const VdpEnergyTaxSummary: React.FunctionComponent<VdpEnergyTaxSummaryProps> = ({ vehicle, t }) => {
|
|
437
|
+
const s: EnergyTaxSummary | undefined = vehicle.energyTaxSummary;
|
|
438
|
+
if (!s) return null;
|
|
439
|
+
return (
|
|
440
|
+
<div id="vdp-energy-tax">
|
|
441
|
+
<h2 style={summaryCardTitleStyle}>{t('vehicleProps:title.energyTaxSummaryTitle')}</h2>
|
|
442
|
+
<div
|
|
443
|
+
className="vdp-ets-row"
|
|
444
|
+
style={{
|
|
445
|
+
display: 'flex',
|
|
446
|
+
width: '100%',
|
|
447
|
+
gap: 4,
|
|
448
|
+
background: '#F5F7FA',
|
|
449
|
+
borderRadius: 12,
|
|
450
|
+
}}
|
|
451
|
+
>
|
|
452
|
+
<div className="vdp-ets-col vdp-ets-col--first" style={{ flex: 1 }}>
|
|
453
|
+
<div style={energyTaxLabelStyle}>{t('vehicleProps:title.energyCostsYearLabel')}</div>
|
|
454
|
+
<div style={energyTaxValueStyle}>{s.energyCost}</div>
|
|
455
|
+
{/* PHEV: both a Kraftstoffpreis AND a Strompreis line (getBaseFuelPrice returns
|
|
456
|
+
both when hybridPlugin===true) — ICE/BEV each only ever populate one. */}
|
|
457
|
+
{s.fuelPriceNote && s.fuelPriceNote.map((note, i) => (
|
|
458
|
+
<div key={i} style={energyTaxNoteStyle}>
|
|
459
|
+
{note}
|
|
460
|
+
</div>
|
|
461
|
+
))}
|
|
462
|
+
</div>
|
|
463
|
+
<div className="vdp-ets-col" style={{ flex: 1 }}>
|
|
464
|
+
<div style={energyTaxLabelStyle}>{t('vehicleProps:title.vehicleTaxYearLabel')}</div>
|
|
465
|
+
<div style={{ height: 24, ...energyTaxValueStyle }}>
|
|
466
|
+
{s.tax}
|
|
467
|
+
<span style={footnoteStyle}>⁶</span>
|
|
468
|
+
</div>
|
|
469
|
+
</div>
|
|
470
|
+
</div>
|
|
471
|
+
</div>
|
|
472
|
+
);
|
|
473
|
+
};
|
|
474
|
+
|
|
475
|
+
// ---------------------------------------------------------------------------
|
|
476
|
+
// "Mögliche CO₂-Kosten über die nächsten 10 Jahre (15.000 km/Jahr)⁵" — new Figma design,
|
|
477
|
+
// same card grammar as VdpEnergyTaxSummary above (own literal inline styles), 3 equal
|
|
478
|
+
// columns (low/middle/high reference CO2 price) instead of 2.
|
|
479
|
+
// ---------------------------------------------------------------------------
|
|
480
|
+
|
|
481
|
+
export interface VdpCo2CostsSummaryProps {
|
|
482
|
+
vehicle: VehicleDetail;
|
|
483
|
+
t: TranslationFunction;
|
|
484
|
+
}
|
|
485
|
+
|
|
486
|
+
export const VdpCo2CostsSummary: React.FunctionComponent<VdpCo2CostsSummaryProps> = ({ vehicle, t }) => {
|
|
487
|
+
const s = vehicle.co2CostsSummary;
|
|
488
|
+
const rows: RunningCostRow[] = s ? ([s.low, s.middle, s.high].filter(Boolean) as RunningCostRow[]) : [];
|
|
489
|
+
if (!rows.length) return null;
|
|
490
|
+
return (
|
|
491
|
+
<div id="vdp-co2-costs">
|
|
492
|
+
<h2 style={summaryCardTitleStyle}>
|
|
493
|
+
{t('vehicleProps:title.co2CostsSummaryTitle')}
|
|
494
|
+
<span style={{ ...footnoteStyle, fontSize: 19 }}>⁵</span>
|
|
495
|
+
</h2>
|
|
496
|
+
<div
|
|
497
|
+
className="vdp-ccs-row"
|
|
498
|
+
style={{
|
|
499
|
+
display: 'flex',
|
|
500
|
+
width: '100%',
|
|
501
|
+
gap: 4,
|
|
502
|
+
background: '#F5F7FA',
|
|
503
|
+
borderRadius: 12,
|
|
504
|
+
}}
|
|
505
|
+
>
|
|
506
|
+
{rows.map((row, i) => (
|
|
507
|
+
<div
|
|
508
|
+
key={i}
|
|
509
|
+
className={`vdp-ccs-col${i < rows.length - 1 ? ' vdp-ccs-col--divider' : ''}`}
|
|
510
|
+
style={{ flex: 1 }}
|
|
511
|
+
>
|
|
512
|
+
<div style={energyTaxLabelStyle}>{row.label}</div>
|
|
513
|
+
<div style={energyTaxValueStyle}>{row.value}</div>
|
|
514
|
+
</div>
|
|
515
|
+
))}
|
|
516
|
+
</div>
|
|
517
|
+
</div>
|
|
518
|
+
);
|
|
519
|
+
};
|
|
520
|
+
|
|
367
521
|
// ---------------------------------------------------------------------------
|
|
368
522
|
// Equipment list (grouped + searchable)
|
|
369
523
|
// ---------------------------------------------------------------------------
|
|
@@ -524,6 +678,19 @@ export const Co2Label: React.FunctionComponent<Co2LabelProps> = ({ vehicle, t })
|
|
|
524
678
|
</div>
|
|
525
679
|
{/* no EnVKV footer line — Figma drops it (the * on the heading refers to the page-footer
|
|
526
680
|
disclaimer instead); the scale caption above carries the WLTP-kombiniert wording */}
|
|
681
|
+
|
|
682
|
+
{/* Pkw-EnVKV mandatory cost disclosure — moved to the bottom of this same card (Figma) rather
|
|
683
|
+
than standing as its own top-level block; each still gates on its own vehicle data. */}
|
|
684
|
+
{vehicle.energyTaxSummary && (
|
|
685
|
+
<div style={{ paddingTop: 20, borderTop: '1px solid #C5C6D2' }}>
|
|
686
|
+
<VdpEnergyTaxSummary vehicle={vehicle} t={t} />
|
|
687
|
+
</div>
|
|
688
|
+
)}
|
|
689
|
+
{vehicle.co2CostsSummary && (
|
|
690
|
+
<div style={{ marginTop: 22 }}>
|
|
691
|
+
<VdpCo2CostsSummary vehicle={vehicle} t={t} />
|
|
692
|
+
</div>
|
|
693
|
+
)}
|
|
527
694
|
</div>
|
|
528
695
|
);
|
|
529
696
|
};
|
package/vdp/index.ts
CHANGED
|
@@ -29,6 +29,8 @@ export {
|
|
|
29
29
|
VdpHeaderCondition,
|
|
30
30
|
VdpTrustRow,
|
|
31
31
|
VdpSpecTable,
|
|
32
|
+
VdpEnergyTaxSummary,
|
|
33
|
+
VdpCo2CostsSummary,
|
|
32
34
|
EquipmentList,
|
|
33
35
|
Co2Label,
|
|
34
36
|
VehicleDescription,
|
|
@@ -49,6 +51,8 @@ export type {
|
|
|
49
51
|
VdpHeaderCardProps,
|
|
50
52
|
VdpTrustRowProps,
|
|
51
53
|
VdpSpecTableProps,
|
|
54
|
+
VdpEnergyTaxSummaryProps,
|
|
55
|
+
VdpCo2CostsSummaryProps,
|
|
52
56
|
EquipmentListProps,
|
|
53
57
|
Co2LabelProps,
|
|
54
58
|
VehicleDescriptionProps,
|
|
@@ -76,6 +80,9 @@ export type {
|
|
|
76
80
|
VehicleDetail,
|
|
77
81
|
VehicleCondition,
|
|
78
82
|
VdpSpec,
|
|
83
|
+
RunningCostRow,
|
|
84
|
+
EnergyTaxSummary,
|
|
85
|
+
Co2CostsSummary,
|
|
79
86
|
EquipmentGroups,
|
|
80
87
|
PriceHistoryPoint,
|
|
81
88
|
PriceRatingBand,
|
package/vdp/types.ts
CHANGED
|
@@ -60,6 +60,53 @@ export function isZeroSpecValue(formatted: string): boolean {
|
|
|
60
60
|
*/
|
|
61
61
|
export type EquipmentGroups = Record<string, string[]>;
|
|
62
62
|
|
|
63
|
+
/**
|
|
64
|
+
* One "Laufende Kosten pro Jahr" row (ADV-123/ADV-242 — Pkw-EnVKV mandatory cost
|
|
65
|
+
* disclosure). `label` and `value` are already the fully-formatted, translated strings
|
|
66
|
+
* the legacy VDP showed (e.g. label "bei niedrigem Ø CO2-Preis von 50 EUR/t", value
|
|
67
|
+
* "312,50 EUR/Jahr"); `description`, when present, is the required explanatory/
|
|
68
|
+
* uncertainty note for the CO2-cost-scenario rows and must always render visibly —
|
|
69
|
+
* never hide it behind a tooltip-only interaction (ticket requirement).
|
|
70
|
+
*/
|
|
71
|
+
export interface RunningCostRow {
|
|
72
|
+
label: string;
|
|
73
|
+
value: string;
|
|
74
|
+
description?: string;
|
|
75
|
+
}
|
|
76
|
+
|
|
77
|
+
/**
|
|
78
|
+
* "Energiekosten und Kraftfahrzeugsteuer pro Jahr" summary card — new Figma design.
|
|
79
|
+
* Covers petrol/diesel, BEV, and PHEV (fuel-type-branching data). Needs-data: undefined
|
|
80
|
+
* when energyCost/tax can't be computed — fuelPriceNote is separately optional (omitted
|
|
81
|
+
* for BEVs, which have no per-liter fuel price).
|
|
82
|
+
*/
|
|
83
|
+
export interface EnergyTaxSummary {
|
|
84
|
+
/** e.g. "1.508,40 €" — for a BEV, the electricity-cost equivalent (getFuelPrice already
|
|
85
|
+
* branches on fuel type internally). */
|
|
86
|
+
energyCost: string;
|
|
87
|
+
/** e.g. "314,00 €" — OR, for a BEV, the real §3d KraftStG time-limited exemption text
|
|
88
|
+
* ("befristet steuerbefreit"), never a fabricated "0,00 €". */
|
|
89
|
+
tax: string;
|
|
90
|
+
/** 1 line for ICE ("Kraftstoffpreis: 1,95 EUR/l (Jahresdurchschnitt 2023)") or BEV
|
|
91
|
+
* ("Strompreis: 41,60 ct/kWh (Jahresdurchschnitt 2023)"); BOTH lines for a plug-in
|
|
92
|
+
* hybrid (getBaseFuelPrice returns fuelPrice AND powerPrice when hybridPlugin===true) —
|
|
93
|
+
* each rendered on its own line, same style. Omitted entirely (never a guessed value)
|
|
94
|
+
* when the car has no computable per-liter fuel price NOR ct/kWh electricity price. */
|
|
95
|
+
fuelPriceNote?: string[];
|
|
96
|
+
}
|
|
97
|
+
|
|
98
|
+
/**
|
|
99
|
+
* "Mögliche CO₂-Kosten über die nächsten 10 Jahre (15.000 km/Jahr)" summary card — new
|
|
100
|
+
* Figma design, 3-column sibling of EnergyTaxSummary. The label already carries the
|
|
101
|
+
* reference €/t price, so `RunningCostRow.description` is unused here. Needs-data: a
|
|
102
|
+
* scenario missing its value is simply omitted.
|
|
103
|
+
*/
|
|
104
|
+
export interface Co2CostsSummary {
|
|
105
|
+
low?: RunningCostRow;
|
|
106
|
+
middle?: RunningCostRow;
|
|
107
|
+
high?: RunningCostRow;
|
|
108
|
+
}
|
|
109
|
+
|
|
63
110
|
/** Vehicle condition block rendered as the header card's zustand tiles. */
|
|
64
111
|
export interface VehicleCondition {
|
|
65
112
|
/** TÜV/HU validity, e.g. '03/2027' — or 'Neu' for a new HU. */
|
|
@@ -163,6 +210,12 @@ export interface VehicleDetail {
|
|
|
163
210
|
*/
|
|
164
211
|
specs?: VdpSpec[];
|
|
165
212
|
|
|
213
|
+
// --- Pkw-EnVKV mandatory cost disclosure (ADV-123/ADV-242) ---
|
|
214
|
+
/** Needs-data: undefined when energyCost/tax can't be computed. */
|
|
215
|
+
energyTaxSummary?: EnergyTaxSummary;
|
|
216
|
+
/** Needs-data: undefined when no CO2-cost scenario can be computed. */
|
|
217
|
+
co2CostsSummary?: Co2CostsSummary;
|
|
218
|
+
|
|
166
219
|
// --- price (always real) ---
|
|
167
220
|
/** financing monthly rate in EUR — the lead price shown in sticky/bottom bars. */
|
|
168
221
|
monthly: number;
|