/* global React */ // ACN-Cars · Shared icons & small UI atoms const Icon = { Heart: ({ filled }) => ( ), Compare: () => ( ), Info2: () => ( ), Shield: () => ( ), Clock: () => ( ), Handshake: () => ( ), User: () => ( ), Mail: () => ( ), Phone: () => ( ), Card: () => ( ), MessageSquare: () => ( ), ArrowLeft: ({ size = 16 }) => ( ), ArrowRight: ({ size = 16 }) => ( ), Check: () => ( ), Plus: () => ( ), WhatsApp: () => ( ), Search: () => ( ), Map: () => ( ), Cal: () => ( ), Sun: () => ( ), Moon: () => ( ), Sparkle: () => ( ), Bolt: () => ( ), Info: () => ( ), }; // Format CHF function chf(n) { return new Intl.NumberFormat("de-CH", { minimumFractionDigits: 0, maximumFractionDigits: 0 }).format(Math.round(n)); } // Spec pill row used on cards function SpecPills({ vehicle }) { return (
{vehicle.transmission} {vehicle.fuel} {vehicle.seats} Plätze {vehicle.power} PS
); } // Live countdown function Countdown({ to }) { const [, setTick] = React.useState(0); React.useEffect(() => { const id = setInterval(() => setTick(t => t + 1), 1000); return () => clearInterval(id); }, []); const ms = Math.max(0, to - Date.now()); const s = Math.floor(ms / 1000); const d = Math.floor(s / 86400); const h = Math.floor((s % 86400) / 3600); const m = Math.floor((s % 3600) / 60); const sec = s % 60; const cell = (n, l) => (
{String(n).padStart(2, "0")}
{l}
); return (
{d > 0 && cell(d, "TAG")} {cell(h, "STD")} {cell(m, "MIN")} {cell(sec, "SEK")}
); } // Helper: Inkl. km für gewählte Stunden — spiegelt die Server-Logik aus class-acn-rest.php // v2.2.44 — Per-Tier-Override (kmIncluded-Map mit explizit eingestellten km_3h/km_6h/...) // hat IMMER Vorrang. kmPerDay nur als Fallback wenn keine Tier-Map vorhanden ist. // Vorher (v2.2.38) hat kmPerDay die im Backend gepflegten Tier-Werte ignoriert → // Symptom: Backend km_6h = 180 km, Frontend zeigt 55 km (= 220 * 6/24). function ACN_kmIncludedFor(vehicle, hours) { if (!vehicle) return 0; const h = Math.max(1, parseInt(hours, 10) || 1); // 1) PRIORITÄT: kmIncluded-Map (Per-Tier-Override aus Backend) // Wenn der Admin pro Tier explizit km_3h/km_6h/km_24h/... eingetragen hat, // haben diese Werte Vorrang vor jeder Berechnung. const m = vehicle && vehicle.kmIncluded; if (m && typeof m === "object") { // Exakter Match (z.B. 6 Std → m["6"]) if (m[String(h)] != null && parseInt(m[String(h)], 10) > 0) { return parseInt(m[String(h)], 10); } // ≥ 1 Woche: nächste Woche aufrunden if (h >= 168 && parseInt(m["168"], 10) > 0) { const weeks = Math.ceil(h / 168); return parseInt(m["168"], 10) * weeks; } // Bucket-Match: nächstgrösserer eingetragener Tier (z.B. 4 Std → m["6"]) const buckets = [1, 3, 6, 24, 48, 72, 168]; for (const b of buckets) { if (h <= b && m[String(b)] != null && parseInt(m[String(b)], 10) > 0) { return parseInt(m[String(b)], 10); } } } // 2) Fallback: kmPerDay-Modell (nur wenn keine Tier-Map vorhanden) const perDay = parseInt(vehicle.kmPerDay, 10); if (perDay > 0) { if (h <= 24) { const val = Math.round(perDay * (h / 24)); return Math.max(30, val); } const days = Math.ceil(h / 24); return perDay * days; } return 0; } Object.assign(window, { Icon, chf, SpecPills, Countdown, ACN_kmIncludedFor });