@bytebrand/fe-ui-core-autobahn 1.0.77 → 1.0.78
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/cards/cardParts.tsx +7 -2
- package/constants.ts +31 -31
- package/locales/de/autobahn.json +2 -2
- package/locales/en/autobahn.json +1 -1
- package/package.json +1 -1
- package/theme/md3.css +216 -83
- package/utils/financeFormat.ts +62 -62
- package/utils/priceRating.ts +58 -58
- package/vdp/FinanceCalculator.tsx +151 -29
- package/vdp/VdpModules.tsx +367 -51
package/vdp/VdpModules.tsx
CHANGED
|
@@ -24,10 +24,10 @@
|
|
|
24
24
|
import React, { useState } from 'react';
|
|
25
25
|
import { TranslationFunction } from '../types';
|
|
26
26
|
|
|
27
|
-
import { Button, Dropdown, DropdownOption, Icon, Spec, StatChip, Stars
|
|
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
29
|
import { defaultVdpSpecs, EquipmentGroups, PriceRatingBands, VehicleDetail, VdpSpec, VdpReview } from './types';
|
|
30
|
-
import { CalcRow, DocCheckIcon, EvalBar, expanderBtnStyle, FinanceMode, Slider, TermChips } from './FinanceCalculator';
|
|
30
|
+
import { CalcRow, DocCheckIcon, EvalBar, expanderBtnStyle, FinanceMode, Slider, TermChips, ToggleRow } from './FinanceCalculator';
|
|
31
31
|
import { formatEur as eur, formatPct as pct } from '../utils/financeFormat';
|
|
32
32
|
|
|
33
33
|
/** Figma "check with open arc" glyph (modern lucide circle-check-big; the bundled lucide
|
|
@@ -1464,6 +1464,14 @@ export interface VdpBottomBarProps {
|
|
|
1464
1464
|
onCall?: () => void;
|
|
1465
1465
|
/** opens the "Rate anpassen" sheet; when omitted the button is not rendered. */
|
|
1466
1466
|
onOpenAdjust?: () => void;
|
|
1467
|
+
/** current down payment (fin) / Sonderzahlung (leasing) in EUR — drives the .fin-cond line. */
|
|
1468
|
+
down?: number;
|
|
1469
|
+
/** current term in months — drives the .fin-cond line. */
|
|
1470
|
+
term?: number;
|
|
1471
|
+
/** leasing annual mileage (km/yr) — leasing-only part of the .fin-cond line. */
|
|
1472
|
+
annualMileage?: number;
|
|
1473
|
+
/** opens the Finanzierungs-/Leasingdetails popup (expanded); when omitted the link is hidden. */
|
|
1474
|
+
onShowDetails?: () => void;
|
|
1467
1475
|
/** i18n function (drilled from the page). */
|
|
1468
1476
|
t: TranslationFunction;
|
|
1469
1477
|
}
|
|
@@ -1482,6 +1490,10 @@ export const VdpBottomBar: React.FunctionComponent<VdpBottomBarProps> = ({
|
|
|
1482
1490
|
onSecure,
|
|
1483
1491
|
onCall,
|
|
1484
1492
|
onOpenAdjust,
|
|
1493
|
+
down,
|
|
1494
|
+
term,
|
|
1495
|
+
annualMileage,
|
|
1496
|
+
onShowDetails,
|
|
1485
1497
|
t,
|
|
1486
1498
|
}) => {
|
|
1487
1499
|
const [uvpTooltipOpen, setUvpTooltipOpen] = useState(false);
|
|
@@ -1495,6 +1507,21 @@ export const VdpBottomBar: React.FunctionComponent<VdpBottomBarProps> = ({
|
|
|
1495
1507
|
const evalTierLabel = isGoodTier ? t('autobahn:tier.top') : t('autobahn:tier.' + TIER_KEYS[evalTier]);
|
|
1496
1508
|
const evalPillColor = isGoodTier ? TIER_COLORS[0] : TIER_COLORS[evalTier];
|
|
1497
1509
|
const evalPillBackground = isGoodTier ? TIER_BACKGROUNDS[0] : TIER_BACKGROUNDS[evalTier];
|
|
1510
|
+
// condition summary — same wording/order as FinanceCalculator's own .fin-cond (financing
|
|
1511
|
+
// "0 € Anzahlung · 60 Monate", leasing "0 € Sonderzahlung · 36 Mon. · 10.000 km/Jahr").
|
|
1512
|
+
const condParts: string[] = [];
|
|
1513
|
+
if (mode === 'leasing') {
|
|
1514
|
+
condParts.push(
|
|
1515
|
+
...t('autobahn:card.price.leaseTerms', {
|
|
1516
|
+
firstInstallment: eur(down || 0),
|
|
1517
|
+
months: term,
|
|
1518
|
+
mileage: annualMileage != null ? eur(annualMileage) : '',
|
|
1519
|
+
}).split(' · '),
|
|
1520
|
+
);
|
|
1521
|
+
} else if (!isCash) {
|
|
1522
|
+
condParts.push(t('autobahn:finance.downPaymentLabel', { value: eur(down || 0) }));
|
|
1523
|
+
condParts.push(t('autobahn:finance.monthsLabel', { months: term, count: term }));
|
|
1524
|
+
}
|
|
1498
1525
|
const priceStyle: React.CSSProperties = isCash
|
|
1499
1526
|
? {
|
|
1500
1527
|
fontFamily: 'Arial, Helvetica, sans-serif',
|
|
@@ -1665,6 +1692,24 @@ export const VdpBottomBar: React.FunctionComponent<VdpBottomBarProps> = ({
|
|
|
1665
1692
|
</div>
|
|
1666
1693
|
)}
|
|
1667
1694
|
</div>
|
|
1695
|
+
{!isCash && (
|
|
1696
|
+
<div className="fin-cond">
|
|
1697
|
+
{condParts.map((part, i) => (
|
|
1698
|
+
<React.Fragment key={i}>
|
|
1699
|
+
{i > 0 && <span className="cc-terms-dot"> · </span>}
|
|
1700
|
+
{part}
|
|
1701
|
+
</React.Fragment>
|
|
1702
|
+
))}
|
|
1703
|
+
{onShowDetails && (
|
|
1704
|
+
<>
|
|
1705
|
+
<span className="cc-terms-dot"> · </span>
|
|
1706
|
+
<button type="button" className="cc-terms-link" onClick={onShowDetails}>
|
|
1707
|
+
{mode === 'leasing' ? t('autobahn:card.price.detailsLink') : t('autobahn:finance.financingDetails')}
|
|
1708
|
+
</button>
|
|
1709
|
+
</>
|
|
1710
|
+
)}
|
|
1711
|
+
</div>
|
|
1712
|
+
)}
|
|
1668
1713
|
<div className="bb-cta-row">
|
|
1669
1714
|
<Button
|
|
1670
1715
|
variant="filled"
|
|
@@ -1776,40 +1821,8 @@ export const InspectionBlock: React.FunctionComponent<InspectionBlockProps> = ({
|
|
|
1776
1821
|
// Finanzierungs-/Leasingdetails popup (desktop modal / mobile bottom-sheet)
|
|
1777
1822
|
// ---------------------------------------------------------------------------
|
|
1778
1823
|
|
|
1779
|
-
|
|
1780
|
-
|
|
1781
|
-
* Switch's `label` prop (which renders track-then-label, not a full-width justified row). */
|
|
1782
|
-
const ToggleRow: React.FunctionComponent<{
|
|
1783
|
-
label: string;
|
|
1784
|
-
price?: string;
|
|
1785
|
-
checked: boolean;
|
|
1786
|
-
disabled?: boolean;
|
|
1787
|
-
onChange: (checked: boolean) => void;
|
|
1788
|
-
className?: string;
|
|
1789
|
-
/** cash mode: the package is always included — shows a static "inklusive" note instead of the switch. */
|
|
1790
|
-
staticNote?: string;
|
|
1791
|
-
}> = ({ label, price, checked, disabled, onChange, className, staticNote }) => (
|
|
1792
|
-
<div className={className} style={{ display: 'flex', alignItems: 'center', justifyContent: staticNote ? undefined : 'space-between', gap: 10 }}>
|
|
1793
|
-
<span className="md-title-sm" style={{ display: 'inline-flex', alignItems: 'center', gap: 5 }}>
|
|
1794
|
-
{label}
|
|
1795
|
-
<Icon name="info" size={13} color="var(--md-on-surface-variant)" />
|
|
1796
|
-
</span>
|
|
1797
|
-
<div style={{ display: 'flex', alignItems: 'center', gap: 10, marginLeft: staticNote ? 'auto' : undefined }}>
|
|
1798
|
-
{price && (
|
|
1799
|
-
<span className="num" style={{ fontWeight: 700, fontSize: 13.5, marginRight: staticNote ? 'auto' : undefined }}>
|
|
1800
|
-
{price}
|
|
1801
|
-
</span>
|
|
1802
|
-
)}
|
|
1803
|
-
{staticNote ? (
|
|
1804
|
-
<span style={{ fontFamily: 'Arial', fontWeight: 400, fontSize: 15, lineHeight: '17px', color: '#0E2238' }}>
|
|
1805
|
-
{staticNote}
|
|
1806
|
-
</span>
|
|
1807
|
-
) : (
|
|
1808
|
-
<Switch checked={checked} disabled={disabled} onChange={(e) => onChange(e.target.checked)} ariaLabel={label} />
|
|
1809
|
-
)}
|
|
1810
|
-
</div>
|
|
1811
|
-
</div>
|
|
1812
|
-
);
|
|
1824
|
+
// ToggleRow lives in FinanceCalculator.tsx (imported above) — shared with the desktop
|
|
1825
|
+
// .fin-calc-card's own "Rate anpassen" panel, which needs the same toggles.
|
|
1813
1826
|
|
|
1814
1827
|
export interface FinanceDetailsModalProps {
|
|
1815
1828
|
/** open flag (controlled by the page). */
|
|
@@ -1943,10 +1956,10 @@ export const FinanceDetailsModal: React.FunctionComponent<FinanceDetailsModalPro
|
|
|
1943
1956
|
// modal's mobile "Rate anpassen" sheet renders its own separate copy of that hero row, so it
|
|
1944
1957
|
// needs its own tooltip-open state (not shared with FinanceCalculator's instance).
|
|
1945
1958
|
const [uvpTooltipOpen, setUvpTooltipOpen] = React.useState(false);
|
|
1946
|
-
// opened directly via the "Finanzierungsdetails" link (initialShowBreakdown) —
|
|
1947
|
-
//
|
|
1948
|
-
// the top
|
|
1949
|
-
//
|
|
1959
|
+
// opened directly via the "Finanzierungsdetails" link (initialShowBreakdown) — on mobile the
|
|
1960
|
+
// breakdown is still gated behind its own toggle, so scroll the sheet down to reveal it instead
|
|
1961
|
+
// of leaving the user at the top. Desktop always shows the breakdown inline now (no toggle), so
|
|
1962
|
+
// it's excluded here — scrolling straight past the price/sliders/toggles on open was jarring.
|
|
1950
1963
|
const desktopBreakdownRef = React.useRef<HTMLDivElement | null>(null);
|
|
1951
1964
|
const mobileBreakdownRef = React.useRef<HTMLDivElement | null>(null);
|
|
1952
1965
|
React.useEffect(() => {
|
|
@@ -1954,8 +1967,8 @@ export const FinanceDetailsModal: React.FunctionComponent<FinanceDetailsModalPro
|
|
|
1954
1967
|
setShowBreakdown(!!initialShowBreakdown);
|
|
1955
1968
|
if (!initialShowBreakdown) return;
|
|
1956
1969
|
const timer = window.setTimeout(() => {
|
|
1957
|
-
const target =
|
|
1958
|
-
target
|
|
1970
|
+
const target = mobileBreakdownRef.current;
|
|
1971
|
+
if (target && target.offsetParent !== null) target.scrollIntoView({ behavior: 'smooth', block: 'start' });
|
|
1959
1972
|
}, 50);
|
|
1960
1973
|
return () => window.clearTimeout(timer);
|
|
1961
1974
|
// eslint-disable-next-line react-hooks/exhaustive-deps
|
|
@@ -2176,7 +2189,8 @@ export const FinanceDetailsModal: React.FunctionComponent<FinanceDetailsModalPro
|
|
|
2176
2189
|
</button>
|
|
2177
2190
|
</div>
|
|
2178
2191
|
<div className="fin-modal-body">
|
|
2179
|
-
{/* ============================== DESKTOP (≥601px) —
|
|
2192
|
+
{/* ============================== DESKTOP (≥601px) — always-expanded breakdown, no tabs
|
|
2193
|
+
(the desktop .fin-calc-card owns its own tabs outside this modal) ============================== */}
|
|
2180
2194
|
<div className="hide-mobile">
|
|
2181
2195
|
<div style={{ display: 'flex', alignItems: 'baseline', gap: 6, marginBottom: 14 }}>
|
|
2182
2196
|
<span className="num" style={{ fontSize: 34, fontWeight: 800, color: 'var(--md-primary)', letterSpacing: '-1px' }}>
|
|
@@ -2225,14 +2239,303 @@ export const FinanceDetailsModal: React.FunctionComponent<FinanceDetailsModalPro
|
|
|
2225
2239
|
<div className="md-title-sm" style={{ marginBottom: 8 }}>
|
|
2226
2240
|
{t('autobahn:finance.termSelection')}
|
|
2227
2241
|
</div>
|
|
2228
|
-
<TermChips
|
|
2242
|
+
<TermChips
|
|
2243
|
+
options={termVals.filter((v) => v !== 12 && v !== 96)}
|
|
2244
|
+
value={term}
|
|
2245
|
+
onChange={onTermChange as (n: number) => void}
|
|
2246
|
+
t={t}
|
|
2247
|
+
/>
|
|
2229
2248
|
</div>
|
|
2230
2249
|
</div>
|
|
2231
2250
|
)}
|
|
2232
|
-
|
|
2233
|
-
|
|
2234
|
-
|
|
2235
|
-
|
|
2251
|
+
{/* same Mit-Schlussrate / Rundum-Sorglos-Paket toggles as the mobile sheet — desktop
|
|
2252
|
+
had neither before, silently dropping two controls the mobile view already had. */}
|
|
2253
|
+
{!isCash && !isLease && onToggleFinalInstallment && (
|
|
2254
|
+
<ToggleRow
|
|
2255
|
+
className="fin-toggle-final"
|
|
2256
|
+
label={t('autobahn:finance.finalInstallmentToggle')}
|
|
2257
|
+
checked={!!withFinalInstallment}
|
|
2258
|
+
onChange={onToggleFinalInstallment}
|
|
2259
|
+
/>
|
|
2260
|
+
)}
|
|
2261
|
+
{!isCash && addServicesCost != null && onToggleAddServices && (
|
|
2262
|
+
<ToggleRow
|
|
2263
|
+
className={'fin-toggle-addservices' + (isLease ? ' fin-toggle-addservices--leasing' : '')}
|
|
2264
|
+
label={t('autobahn:finance.addServicesToggle')}
|
|
2265
|
+
price={t('autobahn:finance.addServicesPerMonth', { value: eur(Math.round(addServicesCost)) })}
|
|
2266
|
+
checked={!!withAddServices}
|
|
2267
|
+
disabled={addServicesDisabled}
|
|
2268
|
+
onChange={onToggleAddServices}
|
|
2269
|
+
/>
|
|
2270
|
+
)}
|
|
2271
|
+
<div ref={desktopBreakdownRef} style={!isCash ? { marginTop: 18 } : undefined}>
|
|
2272
|
+
{!isCash && (
|
|
2273
|
+
<>
|
|
2274
|
+
<p
|
|
2275
|
+
style={{
|
|
2276
|
+
fontFamily: 'Arial, Helvetica, sans-serif',
|
|
2277
|
+
fontWeight: 700,
|
|
2278
|
+
fontSize: 16,
|
|
2279
|
+
lineHeight: '18px',
|
|
2280
|
+
color: '#0E2238',
|
|
2281
|
+
margin: 0,
|
|
2282
|
+
marginBottom: 5,
|
|
2283
|
+
}}
|
|
2284
|
+
>
|
|
2285
|
+
{t('autobahn:modal.representativeExample')}
|
|
2286
|
+
</p>
|
|
2287
|
+
<p
|
|
2288
|
+
style={{
|
|
2289
|
+
fontFamily: 'Arial, Helvetica, sans-serif',
|
|
2290
|
+
fontWeight: 700,
|
|
2291
|
+
fontSize: 9,
|
|
2292
|
+
lineHeight: '12px',
|
|
2293
|
+
color: '#5B6B7F',
|
|
2294
|
+
marginBottom: 5,
|
|
2295
|
+
}}
|
|
2296
|
+
>
|
|
2297
|
+
{t('autobahn:modal.vatDisclaimer')}
|
|
2298
|
+
</p>
|
|
2299
|
+
</>
|
|
2300
|
+
)}
|
|
2301
|
+
{breakdownRows}
|
|
2302
|
+
</div>
|
|
2303
|
+
{isCash ? (
|
|
2304
|
+
<p className="md-label-sm" style={{ marginTop: 16, lineHeight: 1.55 }}>
|
|
2305
|
+
{isLease ? t('autobahn:modal.legalLeasing') : t('autobahn:modal.legalFinancing')}
|
|
2306
|
+
</p>
|
|
2307
|
+
) : (
|
|
2308
|
+
<>
|
|
2309
|
+
{/* Darlehensgeber disclosure box — same content as the mobile "Finanzierungs-Details"
|
|
2310
|
+
expander, just always visible on desktop instead of gated behind a toggle. */}
|
|
2311
|
+
<div
|
|
2312
|
+
style={{
|
|
2313
|
+
display: 'flex',
|
|
2314
|
+
alignItems: 'flex-start',
|
|
2315
|
+
gap: 10,
|
|
2316
|
+
background: '#FAFBFD',
|
|
2317
|
+
border: '1px solid #D4DDE7',
|
|
2318
|
+
borderRadius: 6,
|
|
2319
|
+
padding: 10,
|
|
2320
|
+
marginTop: 10,
|
|
2321
|
+
marginBottom: 10,
|
|
2322
|
+
}}
|
|
2323
|
+
>
|
|
2324
|
+
<svg width="27" height="27" viewBox="0 0 27 27" fill="none" xmlns="http://www.w3.org/2000/svg" style={{ flex: 'none' }}>
|
|
2325
|
+
<path d="M2.7002 9.00001L13.5002 3.60001L24.3002 9.00001H2.7002Z" stroke="#0E2238" strokeWidth="1.6" strokeLinejoin="round" />
|
|
2326
|
+
<path d="M4.49961 10.8H22.4996M5.39961 21.6H21.5996M3.59961 24.3H23.3996" stroke="#0E2238" strokeWidth="1.6" strokeLinecap="round" />
|
|
2327
|
+
<path d="M7.2002 10.8V21.6M11.7002 10.8V21.6M15.3002 10.8V21.6M19.8002 10.8V21.6" stroke="#0E2238" strokeWidth="1.6" />
|
|
2328
|
+
</svg>
|
|
2329
|
+
<div style={{ width: '100%' }}>
|
|
2330
|
+
<p
|
|
2331
|
+
style={{
|
|
2332
|
+
fontFamily: 'Arial, Helvetica, sans-serif',
|
|
2333
|
+
fontWeight: 700,
|
|
2334
|
+
fontSize: 14,
|
|
2335
|
+
lineHeight: '13px',
|
|
2336
|
+
color: '#0E2238',
|
|
2337
|
+
margin: 0,
|
|
2338
|
+
marginBottom: 3,
|
|
2339
|
+
}}
|
|
2340
|
+
>
|
|
2341
|
+
{isLease ? t('autobahn:modal.leaseLenderLabel') : t('autobahn:modal.lenderLabel')}
|
|
2342
|
+
</p>
|
|
2343
|
+
<p
|
|
2344
|
+
style={{
|
|
2345
|
+
fontFamily: 'Arial, Helvetica, sans-serif',
|
|
2346
|
+
fontWeight: 400,
|
|
2347
|
+
fontSize: 12,
|
|
2348
|
+
lineHeight: '13px',
|
|
2349
|
+
color: '#0E2238',
|
|
2350
|
+
margin: 0,
|
|
2351
|
+
}}
|
|
2352
|
+
>
|
|
2353
|
+
{isLease ? t('autobahn:modal.leaseLenderName') : t('autobahn:modal.lenderName')}
|
|
2354
|
+
</p>
|
|
2355
|
+
{isLease && (
|
|
2356
|
+
<>
|
|
2357
|
+
<div style={{ height: 1, background: '#D6DEE8', margin: '8px 0' }} />
|
|
2358
|
+
<p
|
|
2359
|
+
style={{
|
|
2360
|
+
fontFamily: 'Arial, Helvetica, sans-serif',
|
|
2361
|
+
fontWeight: 700,
|
|
2362
|
+
fontSize: 14,
|
|
2363
|
+
lineHeight: '13px',
|
|
2364
|
+
color: '#0E2238',
|
|
2365
|
+
margin: 0,
|
|
2366
|
+
marginBottom: 3,
|
|
2367
|
+
}}
|
|
2368
|
+
>
|
|
2369
|
+
{t('autobahn:modal.contractTypeLabel')}
|
|
2370
|
+
</p>
|
|
2371
|
+
<p
|
|
2372
|
+
style={{
|
|
2373
|
+
fontFamily: 'Arial, Helvetica, sans-serif',
|
|
2374
|
+
fontWeight: 400,
|
|
2375
|
+
fontSize: 12,
|
|
2376
|
+
lineHeight: '13px',
|
|
2377
|
+
color: '#0E2238',
|
|
2378
|
+
margin: 0,
|
|
2379
|
+
}}
|
|
2380
|
+
>
|
|
2381
|
+
{t('autobahn:modal.contractTypeValue')}
|
|
2382
|
+
</p>
|
|
2383
|
+
</>
|
|
2384
|
+
)}
|
|
2385
|
+
</div>
|
|
2386
|
+
</div>
|
|
2387
|
+
{isLease && hasAddServicesRow && (
|
|
2388
|
+
<div
|
|
2389
|
+
style={{
|
|
2390
|
+
display: 'flex',
|
|
2391
|
+
alignItems: 'flex-start',
|
|
2392
|
+
gap: 10,
|
|
2393
|
+
background: '#F7FAFE',
|
|
2394
|
+
border: '0.5px solid #D6DEE8',
|
|
2395
|
+
borderRadius: 5,
|
|
2396
|
+
padding: '7px 8px',
|
|
2397
|
+
marginBottom: 10,
|
|
2398
|
+
}}
|
|
2399
|
+
>
|
|
2400
|
+
<svg width="12" height="12" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg" style={{ flex: 'none', marginTop: 2 }}>
|
|
2401
|
+
<circle cx="12" cy="12" r="10" stroke="#0E2238" strokeWidth="1.6" />
|
|
2402
|
+
<path d="M12 16v-4" stroke="#0E2238" strokeWidth="1.6" strokeLinecap="round" />
|
|
2403
|
+
<path d="M12 8h.01" stroke="#0E2238" strokeWidth="1.6" strokeLinecap="round" />
|
|
2404
|
+
</svg>
|
|
2405
|
+
<p
|
|
2406
|
+
style={{
|
|
2407
|
+
fontFamily: 'Arial, Helvetica, sans-serif',
|
|
2408
|
+
fontWeight: 400,
|
|
2409
|
+
fontSize: 10,
|
|
2410
|
+
lineHeight: '10px',
|
|
2411
|
+
textAlign: 'justify',
|
|
2412
|
+
color: '#0E2238',
|
|
2413
|
+
margin: 0,
|
|
2414
|
+
}}
|
|
2415
|
+
>
|
|
2416
|
+
{t('autobahn:modal.packageMandatoryNotice', { amount: eur(addServicesCostRaw ?? 0) })}
|
|
2417
|
+
</p>
|
|
2418
|
+
</div>
|
|
2419
|
+
)}
|
|
2420
|
+
<p
|
|
2421
|
+
style={{
|
|
2422
|
+
fontFamily: 'Arial, Helvetica, sans-serif',
|
|
2423
|
+
fontWeight: 700,
|
|
2424
|
+
fontSize: 13.3,
|
|
2425
|
+
lineHeight: '17px',
|
|
2426
|
+
color: '#0E2238',
|
|
2427
|
+
margin: 0,
|
|
2428
|
+
marginBottom: 7,
|
|
2429
|
+
}}
|
|
2430
|
+
>
|
|
2431
|
+
{t('autobahn:modal.legalNoticesTitle')}
|
|
2432
|
+
</p>
|
|
2433
|
+
{isLease ? (
|
|
2434
|
+
<>
|
|
2435
|
+
<p style={{ fontFamily: 'Arial, Helvetica, sans-serif', fontWeight: 400, fontSize: 12, lineHeight: '12px', color: '#0E2238', margin: 0, marginBottom: 5 }}>
|
|
2436
|
+
{t('autobahn:modal.legalFootnoteAcquisitionPrice')}
|
|
2437
|
+
</p>
|
|
2438
|
+
<p style={{ fontFamily: 'Arial, Helvetica, sans-serif', fontWeight: 400, fontSize: 12, lineHeight: '12px', color: '#0E2238', margin: 0, marginBottom: 10 }}>
|
|
2439
|
+
{t('autobahn:modal.legalFootnoteListPriceLease')}
|
|
2440
|
+
</p>
|
|
2441
|
+
<p
|
|
2442
|
+
style={{
|
|
2443
|
+
fontFamily: 'Arial, Helvetica, sans-serif',
|
|
2444
|
+
fontWeight: 400,
|
|
2445
|
+
fontSize: 12,
|
|
2446
|
+
lineHeight: '12px',
|
|
2447
|
+
color: '#0E2238',
|
|
2448
|
+
margin: 0,
|
|
2449
|
+
paddingBottom: 10,
|
|
2450
|
+
}}
|
|
2451
|
+
>
|
|
2452
|
+
{t('autobahn:modal.closingDisclaimerLine1')}
|
|
2453
|
+
<br />
|
|
2454
|
+
{t('autobahn:modal.closingDisclaimerLine2')}
|
|
2455
|
+
</p>
|
|
2456
|
+
</>
|
|
2457
|
+
) : (
|
|
2458
|
+
<>
|
|
2459
|
+
<ul style={{ margin: 0, marginBottom: 3, paddingLeft: 16, display: 'flex', flexDirection: 'column', gap: 3 }}>
|
|
2460
|
+
{[
|
|
2461
|
+
t('autobahn:modal.legalNoticeCreditworthiness'),
|
|
2462
|
+
t('autobahn:modal.legalNoticeExample'),
|
|
2463
|
+
t('autobahn:modal.legalNoticeTwoThirds'),
|
|
2464
|
+
t('autobahn:modal.legalNoticeVat'),
|
|
2465
|
+
t('autobahn:modal.legalNoticeAddServices'),
|
|
2466
|
+
].map((notice) => (
|
|
2467
|
+
<li
|
|
2468
|
+
key={notice}
|
|
2469
|
+
style={{
|
|
2470
|
+
fontFamily: 'Arial, Helvetica, sans-serif',
|
|
2471
|
+
fontWeight: 400,
|
|
2472
|
+
fontSize: 12,
|
|
2473
|
+
lineHeight: '12px',
|
|
2474
|
+
color: '#0E2238',
|
|
2475
|
+
}}
|
|
2476
|
+
>
|
|
2477
|
+
{notice}
|
|
2478
|
+
</li>
|
|
2479
|
+
))}
|
|
2480
|
+
</ul>
|
|
2481
|
+
<p
|
|
2482
|
+
style={{
|
|
2483
|
+
fontFamily: 'Arial, Helvetica, sans-serif',
|
|
2484
|
+
fontWeight: 400,
|
|
2485
|
+
fontSize: 12,
|
|
2486
|
+
lineHeight: '12px',
|
|
2487
|
+
color: '#0E2238',
|
|
2488
|
+
margin: 0,
|
|
2489
|
+
paddingBottom: 10,
|
|
2490
|
+
}}
|
|
2491
|
+
>
|
|
2492
|
+
{t('autobahn:modal.listPriceFootnote')}
|
|
2493
|
+
</p>
|
|
2494
|
+
</>
|
|
2495
|
+
)}
|
|
2496
|
+
<div className="fin-sheet-cta-row" style={{ display: 'flex', gap: 7, marginTop: 4 }}>
|
|
2497
|
+
<Button
|
|
2498
|
+
variant="filled"
|
|
2499
|
+
size="lg"
|
|
2500
|
+
style={{
|
|
2501
|
+
flex: 1,
|
|
2502
|
+
height: 50,
|
|
2503
|
+
background: '#005CFF',
|
|
2504
|
+
borderRadius: 16,
|
|
2505
|
+
justifyContent: 'center',
|
|
2506
|
+
fontFamily: 'Arial, Helvetica, sans-serif',
|
|
2507
|
+
fontWeight: 700,
|
|
2508
|
+
fontSize: 14,
|
|
2509
|
+
lineHeight: '16px',
|
|
2510
|
+
textAlign: 'center',
|
|
2511
|
+
color: '#FFFFFF',
|
|
2512
|
+
}}
|
|
2513
|
+
onClick={onSecure}
|
|
2514
|
+
>
|
|
2515
|
+
<span style={{ display: 'inline-flex', marginRight: 18 }}>
|
|
2516
|
+
<DocCheckIcon size={23} />
|
|
2517
|
+
</span>
|
|
2518
|
+
{t('autobahn:finance.requestRate')}
|
|
2519
|
+
</Button>
|
|
2520
|
+
<Button
|
|
2521
|
+
variant="outlined"
|
|
2522
|
+
size="lg"
|
|
2523
|
+
icon="phone"
|
|
2524
|
+
className="fin-sheet-call-btn"
|
|
2525
|
+
style={{
|
|
2526
|
+
width: 50,
|
|
2527
|
+
height: 50,
|
|
2528
|
+
flex: 'none',
|
|
2529
|
+
padding: 0,
|
|
2530
|
+
background: '#FFFFFF',
|
|
2531
|
+
border: '1.6px solid #005CFF',
|
|
2532
|
+
borderRadius: 16,
|
|
2533
|
+
}}
|
|
2534
|
+
onClick={onCall}
|
|
2535
|
+
/>
|
|
2536
|
+
</div>
|
|
2537
|
+
</>
|
|
2538
|
+
)}
|
|
2236
2539
|
</div>
|
|
2237
2540
|
|
|
2238
2541
|
{/* ============================== MOBILE (≤600px) — full "Rate anpassen" sheet ============================== */}
|
|
@@ -2266,7 +2569,12 @@ export const FinanceDetailsModal: React.FunctionComponent<FinanceDetailsModalPro
|
|
|
2266
2569
|
{/* Figma Kaufen sheet: struck list price ABOVE the price, aligned to its right
|
|
2267
2570
|
edge (inline-beside wraps — the 44px phone hero fills the whole column) */}
|
|
2268
2571
|
{isCash && listPrice != null && listPrice > price && (
|
|
2269
|
-
<div
|
|
2572
|
+
<div
|
|
2573
|
+
style={{ display: 'flex', justifyContent: 'flex-end', lineHeight: 1, marginTop: 0 }}
|
|
2574
|
+
role="button"
|
|
2575
|
+
tabIndex={0}
|
|
2576
|
+
onClick={() => setUvpTooltipOpen((v) => !v)}
|
|
2577
|
+
>
|
|
2270
2578
|
<s className="num fin-rate-old fin-rate-old-list">
|
|
2271
2579
|
{eur(listPrice)} €
|
|
2272
2580
|
<span
|
|
@@ -2333,7 +2641,15 @@ export const FinanceDetailsModal: React.FunctionComponent<FinanceDetailsModalPro
|
|
|
2333
2641
|
</span>
|
|
2334
2642
|
<span className="fin-rate-unit">
|
|
2335
2643
|
{oldMonthly != null && (
|
|
2336
|
-
|
|
2644
|
+
<span
|
|
2645
|
+
style={{ display: 'flex', flexDirection: 'column' }}
|
|
2646
|
+
role="button"
|
|
2647
|
+
tabIndex={0}
|
|
2648
|
+
onClick={(e) => {
|
|
2649
|
+
e.stopPropagation();
|
|
2650
|
+
setUvpTooltipOpen((v) => !v);
|
|
2651
|
+
}}
|
|
2652
|
+
>
|
|
2337
2653
|
<span className="pp-eyebrow">
|
|
2338
2654
|
{t('autobahn:card.price.uvpRateLabel')}
|
|
2339
2655
|
<span
|
|
@@ -2383,7 +2699,7 @@ export const FinanceDetailsModal: React.FunctionComponent<FinanceDetailsModalPro
|
|
|
2383
2699
|
>
|
|
2384
2700
|
{eur(Math.round(oldMonthly))} €
|
|
2385
2701
|
</s>
|
|
2386
|
-
|
|
2702
|
+
</span>
|
|
2387
2703
|
)}
|
|
2388
2704
|
<span className="fin-rate-example-suffix">
|
|
2389
2705
|
{t('autobahn:finance.perMonth')}
|