@bytebrand/fe-ui-core-autobahn 1.0.132 → 1.0.133
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 +30 -30
- package/theme/md3.css +46 -0
- package/vdp/VdpModules.tsx +211 -1
- package/vdp/index.ts +9 -0
- package/vdp/types.ts +53 -0
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.133",
|
|
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
|
@@ -11276,3 +11276,49 @@ color: #005CFF;
|
|
|
11276
11276
|
border-bottom-right-radius: 2px;
|
|
11277
11277
|
}
|
|
11278
11278
|
}
|
|
11279
|
+
|
|
11280
|
+
/* VdpEnergyTaxSummary ("Energiekosten und Kraftfahrzeugsteuer pro Jahr" card, VdpModules.tsx)
|
|
11281
|
+
— desktop layout (row, padding: 15px, border-right divider between the 2 columns) is
|
|
11282
|
+
inline JS styles on the component, untouched. padding + the divider are the only two
|
|
11283
|
+
properties that change on mobile, so THOSE (only) live here instead of inline, letting
|
|
11284
|
+
this media query override them without !important. */
|
|
11285
|
+
.md3 .vdp-ets-col {
|
|
11286
|
+
padding: 15px;
|
|
11287
|
+
}
|
|
11288
|
+
.md3 .vdp-ets-col--first {
|
|
11289
|
+
border-right: 1px solid var(--md-outline-variant);
|
|
11290
|
+
}
|
|
11291
|
+
@media (max-width: 600px) {
|
|
11292
|
+
.md3 .vdp-ets-row {
|
|
11293
|
+
flex-direction: column;
|
|
11294
|
+
}
|
|
11295
|
+
.md3 .vdp-ets-col {
|
|
11296
|
+
padding: 14px 16px;
|
|
11297
|
+
}
|
|
11298
|
+
.md3 .vdp-ets-col--first {
|
|
11299
|
+
border-right: none;
|
|
11300
|
+
border-bottom: 1px solid var(--md-outline-variant);
|
|
11301
|
+
}
|
|
11302
|
+
}
|
|
11303
|
+
|
|
11304
|
+
/* VdpCo2CostsSummary ("Mögliche CO₂-Kosten..." card, VdpModules.tsx) — same treatment as
|
|
11305
|
+
.vdp-ets-* above, just 3 columns (low/middle/high) instead of 2; the first two carry the
|
|
11306
|
+
divider, the last one never does (nothing to its right/below). */
|
|
11307
|
+
.md3 .vdp-ccs-col {
|
|
11308
|
+
padding: 15px;
|
|
11309
|
+
}
|
|
11310
|
+
.md3 .vdp-ccs-col--divider {
|
|
11311
|
+
border-right: 1px solid var(--md-outline-variant);
|
|
11312
|
+
}
|
|
11313
|
+
@media (max-width: 600px) {
|
|
11314
|
+
.md3 .vdp-ccs-row {
|
|
11315
|
+
flex-direction: column;
|
|
11316
|
+
}
|
|
11317
|
+
.md3 .vdp-ccs-col {
|
|
11318
|
+
padding: 14px 16px;
|
|
11319
|
+
}
|
|
11320
|
+
.md3 .vdp-ccs-col--divider {
|
|
11321
|
+
border-right: none;
|
|
11322
|
+
border-bottom: 1px solid var(--md-outline-variant);
|
|
11323
|
+
}
|
|
11324
|
+
}
|
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,216 @@ 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: '#005CFF',
|
|
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: 'var(--md-sc-lowest)',
|
|
449
|
+
borderRadius: 'var(--md-r-md)',
|
|
450
|
+
border: '1px solid var(--md-outline-variant)',
|
|
451
|
+
}}
|
|
452
|
+
>
|
|
453
|
+
<div className="vdp-ets-col vdp-ets-col--first" style={{ flex: 1 }}>
|
|
454
|
+
<div style={energyTaxLabelStyle}>{t('vehicleProps:title.energyCostsYearLabel')}</div>
|
|
455
|
+
<div style={energyTaxValueStyle}>{s.energyCost}</div>
|
|
456
|
+
{/* PHEV: both a Kraftstoffpreis AND a Strompreis line (getBaseFuelPrice returns
|
|
457
|
+
both when hybridPlugin===true) — ICE/BEV each only ever populate one. */}
|
|
458
|
+
{s.fuelPriceNote && s.fuelPriceNote.map((note, i) => (
|
|
459
|
+
<div key={i} style={energyTaxNoteStyle}>
|
|
460
|
+
{note}
|
|
461
|
+
</div>
|
|
462
|
+
))}
|
|
463
|
+
</div>
|
|
464
|
+
<div className="vdp-ets-col" style={{ flex: 1 }}>
|
|
465
|
+
<div style={energyTaxLabelStyle}>{t('vehicleProps:title.vehicleTaxYearLabel')}</div>
|
|
466
|
+
<div style={{ height: 24, ...energyTaxValueStyle }}>
|
|
467
|
+
{s.tax}
|
|
468
|
+
<span style={footnoteStyle}>⁶</span>
|
|
469
|
+
</div>
|
|
470
|
+
</div>
|
|
471
|
+
</div>
|
|
472
|
+
</div>
|
|
473
|
+
);
|
|
474
|
+
};
|
|
475
|
+
|
|
476
|
+
// ---------------------------------------------------------------------------
|
|
477
|
+
// "Mögliche CO₂-Kosten über die nächsten 10 Jahre (15.000 km/Jahr)⁵" — new Figma design,
|
|
478
|
+
// same card grammar as VdpEnergyTaxSummary above (own literal inline styles), 3 equal
|
|
479
|
+
// columns (low/middle/high reference CO2 price) instead of 2.
|
|
480
|
+
// ---------------------------------------------------------------------------
|
|
481
|
+
|
|
482
|
+
export interface VdpCo2CostsSummaryProps {
|
|
483
|
+
vehicle: VehicleDetail;
|
|
484
|
+
t: TranslationFunction;
|
|
485
|
+
}
|
|
486
|
+
|
|
487
|
+
export const VdpCo2CostsSummary: React.FunctionComponent<VdpCo2CostsSummaryProps> = ({ vehicle, t }) => {
|
|
488
|
+
const s = vehicle.co2CostsSummary;
|
|
489
|
+
const rows: RunningCostRow[] = s ? ([s.low, s.middle, s.high].filter(Boolean) as RunningCostRow[]) : [];
|
|
490
|
+
if (!rows.length) return null;
|
|
491
|
+
return (
|
|
492
|
+
<div id="vdp-co2-costs">
|
|
493
|
+
<h2 style={summaryCardTitleStyle}>
|
|
494
|
+
{t('vehicleProps:title.co2CostsSummaryTitle')}
|
|
495
|
+
<span style={{ ...footnoteStyle, fontSize: 19 }}>⁵</span>
|
|
496
|
+
</h2>
|
|
497
|
+
<div
|
|
498
|
+
className="vdp-ccs-row"
|
|
499
|
+
style={{
|
|
500
|
+
display: 'flex',
|
|
501
|
+
width: '100%',
|
|
502
|
+
gap: 4,
|
|
503
|
+
background: 'var(--md-sc-lowest)',
|
|
504
|
+
borderRadius: 'var(--md-r-md)',
|
|
505
|
+
border: '1px solid var(--md-outline-variant)',
|
|
506
|
+
}}
|
|
507
|
+
>
|
|
508
|
+
{rows.map((row, i) => (
|
|
509
|
+
<div
|
|
510
|
+
key={i}
|
|
511
|
+
className={`vdp-ccs-col${i < rows.length - 1 ? ' vdp-ccs-col--divider' : ''}`}
|
|
512
|
+
style={{ flex: 1 }}
|
|
513
|
+
>
|
|
514
|
+
<div style={energyTaxLabelStyle}>{row.label}</div>
|
|
515
|
+
<div style={energyTaxValueStyle}>{row.value}</div>
|
|
516
|
+
</div>
|
|
517
|
+
))}
|
|
518
|
+
</div>
|
|
519
|
+
</div>
|
|
520
|
+
);
|
|
521
|
+
};
|
|
522
|
+
|
|
523
|
+
// ---------------------------------------------------------------------------
|
|
524
|
+
// Legal footnote text for the "⁵"/"⁶" markers used in VdpCo2CostsSummary/VdpEnergyTaxSummary
|
|
525
|
+
// above — real Pkw-EnVKV/§3d KraftStG disclosure copy (verbatim, not paraphrased), plain
|
|
526
|
+
// text (no card/background). Needs-data: each paragraph only shows when its corresponding
|
|
527
|
+
// card above actually rendered (never an orphaned footnote for a marker nobody saw).
|
|
528
|
+
// ---------------------------------------------------------------------------
|
|
529
|
+
|
|
530
|
+
export interface VdpCostFootnotesProps {
|
|
531
|
+
vehicle: VehicleDetail;
|
|
532
|
+
t: TranslationFunction;
|
|
533
|
+
}
|
|
534
|
+
|
|
535
|
+
const costFootnoteStyle: React.CSSProperties = {
|
|
536
|
+
fontFamily: 'Arimo',
|
|
537
|
+
fontStyle: 'normal',
|
|
538
|
+
fontWeight: 700,
|
|
539
|
+
fontSize: 13.5,
|
|
540
|
+
lineHeight: '16px',
|
|
541
|
+
color: '#000000',
|
|
542
|
+
};
|
|
543
|
+
|
|
544
|
+
export const VdpCostFootnotes: React.FunctionComponent<VdpCostFootnotesProps> = ({ vehicle, t }) => {
|
|
545
|
+
const showCo2Footnote = !!vehicle.co2CostsSummary;
|
|
546
|
+
const showTaxFootnote = !!vehicle.energyTaxSummary;
|
|
547
|
+
if (!showCo2Footnote && !showTaxFootnote) return null;
|
|
548
|
+
return (
|
|
549
|
+
<div id="vdp-cost-footnotes" style={costFootnoteStyle}>
|
|
550
|
+
{showCo2Footnote && (
|
|
551
|
+
<>
|
|
552
|
+
{t('vehicleProps:value.co2CostsFootnoteTitle')}
|
|
553
|
+
<br />
|
|
554
|
+
<br />
|
|
555
|
+
{t('vehicleProps:value.co2CostsFootnote')}
|
|
556
|
+
</>
|
|
557
|
+
)}
|
|
558
|
+
{showCo2Footnote && showTaxFootnote && (
|
|
559
|
+
<>
|
|
560
|
+
<br />
|
|
561
|
+
<br />
|
|
562
|
+
<br />
|
|
563
|
+
</>
|
|
564
|
+
)}
|
|
565
|
+
{showTaxFootnote && (
|
|
566
|
+
<>
|
|
567
|
+
{t('vehicleProps:value.taxExemptFootnoteTitle')}
|
|
568
|
+
<br />
|
|
569
|
+
<br />
|
|
570
|
+
{t('vehicleProps:value.taxExemptFootnote')}
|
|
571
|
+
</>
|
|
572
|
+
)}
|
|
573
|
+
</div>
|
|
574
|
+
);
|
|
575
|
+
};
|
|
576
|
+
|
|
367
577
|
// ---------------------------------------------------------------------------
|
|
368
578
|
// Equipment list (grouped + searchable)
|
|
369
579
|
// ---------------------------------------------------------------------------
|
package/vdp/index.ts
CHANGED
|
@@ -29,6 +29,9 @@ export {
|
|
|
29
29
|
VdpHeaderCondition,
|
|
30
30
|
VdpTrustRow,
|
|
31
31
|
VdpSpecTable,
|
|
32
|
+
VdpEnergyTaxSummary,
|
|
33
|
+
VdpCo2CostsSummary,
|
|
34
|
+
VdpCostFootnotes,
|
|
32
35
|
EquipmentList,
|
|
33
36
|
Co2Label,
|
|
34
37
|
VehicleDescription,
|
|
@@ -49,6 +52,9 @@ export type {
|
|
|
49
52
|
VdpHeaderCardProps,
|
|
50
53
|
VdpTrustRowProps,
|
|
51
54
|
VdpSpecTableProps,
|
|
55
|
+
VdpEnergyTaxSummaryProps,
|
|
56
|
+
VdpCo2CostsSummaryProps,
|
|
57
|
+
VdpCostFootnotesProps,
|
|
52
58
|
EquipmentListProps,
|
|
53
59
|
Co2LabelProps,
|
|
54
60
|
VehicleDescriptionProps,
|
|
@@ -76,6 +82,9 @@ export type {
|
|
|
76
82
|
VehicleDetail,
|
|
77
83
|
VehicleCondition,
|
|
78
84
|
VdpSpec,
|
|
85
|
+
RunningCostRow,
|
|
86
|
+
EnergyTaxSummary,
|
|
87
|
+
Co2CostsSummary,
|
|
79
88
|
EquipmentGroups,
|
|
80
89
|
PriceHistoryPoint,
|
|
81
90
|
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;
|