From be5a339b3209d59847b2777e62a29f717469bfc4 Mon Sep 17 00:00:00 2001 From: Leopoldadmin Date: Mon, 13 Jul 2026 09:51:03 +0200 Subject: [PATCH] feat: add UI prototype v8d source files (index.html, app.compiled.js, interactions.js, style.css) --- ui-prototyp/app.compiled.js | 5043 +++++++++++++++++++++++++++++++++++ ui-prototyp/index.html | 19 + ui-prototyp/interactions.js | 563 ++++ ui-prototyp/style.css | 2086 +++++++++++++++ 4 files changed, 7711 insertions(+) create mode 100644 ui-prototyp/app.compiled.js create mode 100644 ui-prototyp/index.html create mode 100644 ui-prototyp/interactions.js create mode 100644 ui-prototyp/style.css diff --git a/ui-prototyp/app.compiled.js b/ui-prototyp/app.compiled.js new file mode 100644 index 0000000..994f919 --- /dev/null +++ b/ui-prototyp/app.compiled.js @@ -0,0 +1,5043 @@ +/* ============================================ + ERP Nutzfahrzeuge - React SPA v4 + ============================================ */ + +const { + useState, + useEffect, + useCallback, + useMemo, + useRef +} = React; + +// ============ ICON COMPONENT ============ +const Icon = ({ + name, + size = 20, + className = '' +}) => { + const icons = { + dashboard: 'M3 13h8V3H3v10zm0 8h8v-6H3v6zm10 0h8V11h-8v10zm0-18v6h8V3h-8z', + truck: 'M1 3h15v13H1V3zm15 5h4l3 3v5h-7V8zM5 18a2 2 0 100-4 2 2 0 000 4zm12 0a2 2 0 100-4 2 2 0 000 4z', + car: 'M5 11l1.5-4.5h11L19 11M3 11h18v6H3v-6zm2 6a1.5 1.5 0 100-3 1.5 1.5 0 000 3zm12 0a1.5 1.5 0 100-3 1.5 1.5 0 000 3z', + forklift: 'M2 20V4h2v14h8v2H2zm2-14h6v8H4V6zm6 0h4v12h-4V6zm4 0h2v12h-2V6zM14 2h6v2h-6V2z', + contacts: 'M16 7a4 4 0 11-8 0 4 4 0 018 0zM2 18c0-3 3-5 6-5s6 2 6 5v1H2v-1zm14-5c2 0 4 2 4 4v1h-4v-5z', + sale: 'M2 4h20v4H2V4zm0 6h12v10H2V10zm14 0h6v6h-6v-6zm0 8h6v2h-6v-2z', + ai: 'M12 2l2 7h7l-5.5 4 2 7L12 16l-5.5 4 2-7L3 9h7l2-7z', + settings: 'M12 8a4 4 0 100 8 4 4 0 000-8z', + users: 'M9 11a4 4 0 100-8 4 4 0 000 8zm0 2c-4 0-7 2-7 5v1h14v-1c0-3-3-5-7-5zm6-2a3 3 0 100-6 3 3 0 000 6z', + search: 'M11 4a7 7 0 100 14 7 7 0 000-14zm10 17l-5-5', + bell: 'M12 2a6 6 0 016 6v4l2 4H4l2-4V8a6 6 0 016-6z', + menu: 'M3 6h18M3 12h18M3 18h18', + close: 'M6 6l12 12M18 6L6 18', + plus: 'M12 5v14M5 12h14', + edit: 'M3 17v4h4l11-11-4-4L3 17z', + trash: 'M3 6h18M8 6V4h8v2M6 6l1 14h10l1-14', + check: 'M5 12l5 5L20 7', + alert: 'M12 2L2 20h20L12 2zm0 7v6m0 4v.01', + info: 'M12 2a10 10 0 100 20 10 10 0 000-20z', + chevronLeft: 'M15 6l-6 6 6 6', + chevronRight: 'M9 6l6 6-6 6', + chevronDown: 'M6 9l6 6 6-6', + arrowUp: 'M12 5v14M5 12l7-7 7 7', + arrowDown: 'M12 5v14M5 12l7 7 7-7', + upload: 'M12 4v12M5 11l7-7 7 7M4 20h16', + download: 'M12 4v12M5 11l7 7 7-7M4 20h16', + camera: 'M3 7h4l2-3h6l2 3h4v12H3V7zm9 3a4 4 0 100 8 4 4 0 000-8z', + mic: 'M12 2a3 3 0 013 3v6a3 3 0 01-6 0V5a3 3 0 013-3z', + send: 'M2 12l20-9-9 20-2-9-9-2z', + sync: 'M4 12a8 8 0 0114-5l2-2v6h-6l2-2a6 6 0 00-10 5H4z', + image: 'M3 4h18v16H3V4zm3 12l4-4 3 3 5-5 3 6H6z', + doc: 'M6 2h10l4 4v16H6V2zm10 0v4h4M9 12h6M9 16h6', + filter: 'M3 6h18l-7 8v6l-4-2v-4L3 6z', + sort: 'M7 4v16M4 7l3-3 3 3M17 20V4M14 17l3 3 3-3', + logout: 'M9 4H5v16h4M16 8l4 4-4 4M9 12h11', + sun: 'M12 8a4 4 0 100 8 4 4 0 000-8z', + moon: 'M21 12a9 9 0 11-9-9 7 7 0 009 9z', + tag: 'M2 12l8-8h12v12l-8 8L2 12zm12-4a2 2 0 100 4 2 2 0 000-4z', + euro: 'M16 8a5 5 0 00-5-3 5 5 0 00-5 7 5 5 0 005 7 5 5 0 005-3M4 11h8M4 13h8', + clock: 'M12 2a10 10 0 100 20 10 10 0 000-20zm0 6v6l4 2', + eye: 'M12 5c-7 0-10 7-10 7s3 7 10 7 10-7 10-7-3-7-10-7zm0 3a4 4 0 100 8 4 4 0 000-8z', + location: 'M12 2a7 7 0 00-7 7c0 5 7 13 7 13s7-8 7-13a7 7 0 00-7-7z', + calendar: 'M3 6h18v15H3V6zm0-2h4V2h2v2h6V2h2v2h4', + trending: 'M3 17l6-6 4 4 8-8M16 7h5v5', + package: 'M12 2L2 7v10l10 5 10-5V7L12 2z', + building: 'M4 4h16v16H4V4z', + shield: 'M12 2L4 6v6c0 5 4 9 8 10 4-1 8-5 8-10V6l-8-4z', + star: 'M12 2l3 7h7l-5.5 4 2 7L12 16l-6.5 4 2-7L2 9h7l3-7z', + list: 'M8 6h13M8 12h13M8 18h13M3 6h.01M3 12h.01M3 18h.01', + grid: 'M3 3h7v7H3V3zm11 0h7v7h-7V3zM3 14h7v7H3v-7zm11 0h7v7h-7v-7z', + external: 'M14 3h7v7M21 3l-9 9', + refresh: 'M4 12a8 8 0 0114-5l2-2v6h-6l2-2a6 6 0 00-10 5H4z', + globe: 'M12 2a10 10 0 100 20 10 10 0 000-20z', + briefcase: 'M3 7h18v13H3V7zM8 7V4h8v3', + phone: 'M6 2h12v20H6V2z', + mail: 'M3 5h18v14H3V5z', + chart: 'M3 3v18h18M7 14l4-4 3 3 5-6', + layers: 'M12 2L2 7l10 5 10-5-10-5z', + wrench: 'M14 6a4 4 0 11-5 5L3 17l4 4 6-6a4 4 0 015-5z', + pdf: 'M6 2h10l4 4v16H6V2z', + sparkles: 'M12 3l1.5 4.5L18 9l-4.5 1.5L12 15l-1.5-4.5L6 9l4.5-1.5L12 3z', + shopping: 'M3 3h2l2 14h12l2-10H6', + gas: 'M3 7v10a2 2 0 002 2h8a2 2 0 002-2V7M3 7h12', + road: 'M5 22V2l4 20M19 22V2l-4 20', + certificate: 'M12 2L4 6v6c0 5 4 9 8 10 4-1 8-5 8-10V6l-8-4z', + percentage: 'M19 5L5 19', + currency: 'M3 8h18M3 16h18', + truck_type: 'M1 3h15v13H1V3z', + clipboard: 'M9 2h6v4H9V2zM4 6h16v16H4V6z', + save: 'M5 3h12l4 4v14H5V3z', + drag: 'M8 6h2v2H8V6zm6 0h2v2h-2V6zM8 11h2v2H8v-2zm6 0h2v2h-2v-2z', + config: 'M12 4a8 8 0 100 16 8 8 0 000-16z' + }; + const path = icons[name] || icons.dashboard; + return /*#__PURE__*/React.createElement("svg", { + width: size, + height: size, + viewBox: "0 0 24 24", + fill: "none", + stroke: "currentColor", + strokeWidth: "2", + strokeLinecap: "round", + strokeLinejoin: "round", + className: className + }, /*#__PURE__*/React.createElement("path", { + d: path + })); +}; + +// ============ SHARED COMPONENTS ============ +const Badge = ({ + variant = 'neutral', + children +}) => /*#__PURE__*/React.createElement("span", { + className: `badge badge-${variant}` +}, children); +const Button = ({ + variant = 'primary', + size = 'md', + icon, + children, + onClick, + disabled, + type = 'button', + className = '', + title +}) => { + const cls = `btn btn-${variant} ${size === 'sm' ? 'btn-sm' : ''} ${size === 'lg' ? 'btn-lg' : ''} ${className}`; + return /*#__PURE__*/React.createElement("button", { + type: type, + className: cls, + onClick: onClick, + disabled: disabled, + title: title + }, icon && /*#__PURE__*/React.createElement(Icon, { + name: icon, + size: size === 'sm' ? 14 : 16 + }), children); +}; +const Card = ({ + title, + action, + children, + className = '' +}) => /*#__PURE__*/React.createElement("div", { + className: `card ${className}` +}, (title || action) && /*#__PURE__*/React.createElement("div", { + className: "card-header" +}, title && /*#__PURE__*/React.createElement("h3", { + className: "card-title" +}, title), action && /*#__PURE__*/React.createElement("div", null, action)), /*#__PURE__*/React.createElement("div", { + className: "card-body" +}, children)); +const KpiCard = ({ + label, + value, + trend, + trendDir, + icon, + color = 'primary' +}) => /*#__PURE__*/React.createElement("div", { + className: "kpi-card" +}, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'flex-start' + } +}, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + className: "kpi-label" +}, t(label)), /*#__PURE__*/React.createElement("div", { + className: "kpi-value" +}, value), trend && /*#__PURE__*/React.createElement("div", { + className: "kpi-trend", + style: { + color: trendDir === 'up' ? 'var(--color-success)' : 'var(--color-error)' + } +}, /*#__PURE__*/React.createElement(Icon, { + name: trendDir === 'up' ? 'arrowUp' : 'arrowDown', + size: 14 +}), /*#__PURE__*/React.createElement("span", null, trend))), icon && /*#__PURE__*/React.createElement("div", { + style: { + width: 40, + height: 40, + borderRadius: 'var(--radius-md)', + background: `var(--color-${color}-light)`, + color: `var(--color-${color})`, + display: 'flex', + alignItems: 'center', + justifyContent: 'center' + } +}, /*#__PURE__*/React.createElement(Icon, { + name: icon, + size: 20 +})))); +const Spinner = ({ + size = 'md' +}) => /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + justifyContent: 'center', + alignItems: 'center', + padding: 'var(--space-12)' + } +}, /*#__PURE__*/React.createElement("div", { + className: `spinner ${size === 'lg' ? 'spinner-lg' : ''}` +})); +const EmptyState = ({ + icon = 'package', + title, + text, + action +}) => /*#__PURE__*/React.createElement("div", { + className: "empty-state" +}, /*#__PURE__*/React.createElement(Icon, { + name: icon, + size: 64, + className: "empty-state-icon" +}), /*#__PURE__*/React.createElement("h3", { + className: "empty-state-title" +}, title), /*#__PURE__*/React.createElement("p", { + className: "empty-state-text" +}, text), action); +const ErrorState = ({ + title, + text, + onRetry +}) => /*#__PURE__*/React.createElement("div", { + className: "error-state" +}, /*#__PURE__*/React.createElement(Icon, { + name: "alert", + size: 48, + className: "error-state-icon" +}), /*#__PURE__*/React.createElement("h3", { + className: "empty-state-title" +}, title || t('common.fehler_aufgetreten')), /*#__PURE__*/React.createElement("p", { + className: "empty-state-text" +}, text || 'Fehler.'), onRetry && /*#__PURE__*/React.createElement(Button, { + variant: "primary", + icon: "refresh", + onClick: onRetry +}, t('common.erneut_versuchen'))); +const Avatar = ({ + name, + size = 'md' +}) => { + const i = name.split(' ').map(n => n[0]).join('').slice(0, 2).toUpperCase(); + return /*#__PURE__*/React.createElement("div", { + className: `avatar ${size === 'lg' ? 'avatar-lg' : ''}` + }, i); +}; +const ViewToggle = ({ + view, + onChange +}) => /*#__PURE__*/React.createElement("div", { + className: "view-toggle" +}, /*#__PURE__*/React.createElement("button", { + className: `view-toggle-btn ${view === 'table' ? 'active' : ''}`, + onClick: () => onChange('table') +}, /*#__PURE__*/React.createElement(Icon, { + name: "list", + size: 16 +}), " Tabelle"), /*#__PURE__*/React.createElement("button", { + className: `view-toggle-btn ${view === 'grid' ? 'active' : ''}`, + onClick: () => onChange('grid') +}, /*#__PURE__*/React.createElement(Icon, { + name: "grid", + size: 16 +}), " Kacheln")); +const useRouter = () => { + const [route, setRoute] = useState(window.location.hash.slice(1) || '/dashboard'); + useEffect(() => { + const h = () => setRoute(window.location.hash.slice(1) || '/dashboard'); + window.addEventListener('hashchange', h); + return () => window.removeEventListener('hashchange', h); + }, []); + const navigate = useCallback(p => { + window.location.hash = p; + }, []); + return { + route, + navigate + }; +}; +const ZBRef = ({ + field +}) => /*#__PURE__*/React.createElement("span", { + className: "zb-field-ref" +}, field); + +// ============ IMAGE MANAGER (v4 with file button) ============ +const photoCategories = [{ + id: 'aussen_front', + label: 'Aussen - Front' +}, { + id: 'aussen_seite', + label: 'Aussen - Seite' +}, { + id: 'aussen_heck', + label: 'Aussen - Heck' +}, { + id: 'innen_armaturen', + label: 'Innen - Armaturen' +}, { + id: 'innen_sitze', + label: 'Innen - Sitze' +}, { + id: 'motorraum', + label: 'Motorraum' +}, { + id: 'schaeden', + label: 'Schaeden' +}, { + id: 'unterboden', + label: 'Unterboden' +}, { + id: 'dokumente', + label: 'Dokumente' +}, { + id: 'sonstiges', + label: 'Sonstiges' +}]; +const ImageManager = ({ + photos, + setPhotos, + role +}) => { + const [uploading, setUploading] = useState(false); + const [lightbox, setLightbox] = useState(null); + const [showRetusche, setShowRetusche] = useState(null); + const [retuscheOption, setRetuscheOption] = useState(null); + const [retuscheLoading, setRetuscheLoading] = useState(false); + const [deleteConfirm, setDeleteConfirm] = useState(null); + const fileInputRef = useRef(null); + const handleUpload = () => { + setUploading(true); + setTimeout(() => { + setPhotos([...photos, { + id: Date.now() + Math.random(), + category: 'sonstiges', + isMain: photos.length === 0 + }]); + setUploading(false); + }, 1500); + }; + const handleFileSelect = e => { + e.stopPropagation(); + handleUpload(); + }; + const setMainPhoto = id => setPhotos(photos.map(p => ({ + ...p, + isMain: p.id === id + }))); + const deletePhoto = id => { + setPhotos(photos.filter(p => p.id !== id)); + setDeleteConfirm(null); + }; + const setPhotoCategory = (id, category) => setPhotos(photos.map(p => p.id === id ? { + ...p, + category + } : p)); + const movePhoto = (id, dir) => { + const idx = photos.findIndex(p => p.id === id); + if (idx < 0) return; + const ni = dir === 'left' ? idx - 1 : idx + 1; + if (ni < 0 || ni >= photos.length) return; + const arr = [...photos]; + [arr[idx], arr[ni]] = [arr[ni], arr[idx]]; + setPhotos(arr); + }; + const handleRetusche = () => { + setRetuscheLoading(true); + setTimeout(() => { + setRetuscheLoading(false); + setShowRetusche(null); + setRetuscheOption(null); + }, 2000); + }; + const catLabel = catId => photoCategories.find(c => c.id === catId)?.label || 'Sonstiges'; + return /*#__PURE__*/React.createElement("div", { + className: "image-manager" + }, role !== 'buchhaltung' && /*#__PURE__*/React.createElement("div", { + className: `image-upload-zone ${uploading ? 'uploading' : ''}`, + onClick: handleUpload + }, uploading ? /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", { + className: "spinner spinner-lg" + }), /*#__PURE__*/React.createElement("p", { + style: { + fontSize: 'var(--font-size-sm)', + color: 'var(--color-text-secondary)' + } + }, "Fotos werden hochgeladen...")) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Icon, { + name: "upload", + size: 48, + className: "image-upload-icon" + }), /*#__PURE__*/React.createElement("div", { + style: { + fontWeight: 'var(--font-weight-medium)' + } + }, "Fotos hochladen (Drag & Drop)"), /*#__PURE__*/React.createElement("p", { + style: { + fontSize: 'var(--font-size-xs)', + color: 'var(--color-text-muted)' + } + }, "JPG, PNG, WEBP · max 50 MB · Mehrfachauswahl"), /*#__PURE__*/React.createElement("div", { + style: { + marginTop: 'var(--space-3)', + display: 'flex', + gap: 'var(--space-2)', + justifyContent: 'center' + } + }, /*#__PURE__*/React.createElement("div", { + className: "file-input-wrapper" + }, /*#__PURE__*/React.createElement(Button, { + variant: "primary", + size: "sm", + icon: "image" + }, "Datei auswaehlen"), /*#__PURE__*/React.createElement("input", { + type: "file", + multiple: true, + accept: "image/*", + ref: fileInputRef, + onChange: handleFileSelect + }))))), photos.length === 0 ? /*#__PURE__*/React.createElement(EmptyState, { + icon: "image", + title: "Keine Fotos vorhanden", + text: "Laden Sie Fotos hoch. Kategorisieren Sie nach Perspektiven und markieren Sie ein Hauptfoto." + }) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 'var(--space-2)' + } + }, /*#__PURE__*/React.createElement("span", { + style: { + fontSize: 'var(--font-size-sm)', + color: 'var(--color-text-secondary)' + } + }, photos.length, " Foto", photos.length !== 1 ? 's' : ''), role !== 'buchhaltung' && /*#__PURE__*/React.createElement("span", { + style: { + fontSize: 'var(--font-size-xs)', + color: 'var(--color-text-muted)' + } + }, /*#__PURE__*/React.createElement(Icon, { + name: "drag", + size: 12 + }), " Sortieren · ", /*#__PURE__*/React.createElement(Icon, { + name: "star", + size: 12 + }), " Hauptfoto")), /*#__PURE__*/React.createElement("div", { + className: "image-gallery" + }, photos.map((photo, idx) => /*#__PURE__*/React.createElement("div", { + key: photo.id, + className: `image-thumb ${photo.isMain ? 'main-photo' : ''}`, + onClick: () => setLightbox(idx) + }, /*#__PURE__*/React.createElement("div", { + className: "image-thumb-placeholder" + }, /*#__PURE__*/React.createElement(Icon, { + name: "image", + size: 32 + }), /*#__PURE__*/React.createElement("span", { + style: { + fontSize: 'var(--font-size-xs)' + } + }, "Foto ", idx + 1)), /*#__PURE__*/React.createElement("div", { + className: "image-thumb-category" + }, catLabel(photo.category)), photo.isMain && /*#__PURE__*/React.createElement("div", { + className: "image-thumb-main-badge" + }, /*#__PURE__*/React.createElement(Icon, { + name: "star", + size: 14 + })), role !== 'buchhaltung' && /*#__PURE__*/React.createElement("div", { + className: "image-thumb-overlay", + onClick: e => e.stopPropagation() + }, /*#__PURE__*/React.createElement("div", { + className: "image-thumb-actions" + }, /*#__PURE__*/React.createElement("button", { + className: `image-thumb-action star ${photo.isMain ? 'active' : ''}`, + title: "Hauptfoto", + onClick: () => setMainPhoto(photo.id) + }, /*#__PURE__*/React.createElement(Icon, { + name: "star", + size: 14 + })), /*#__PURE__*/React.createElement("button", { + className: "image-thumb-action", + title: "Nach links", + onClick: () => movePhoto(photo.id, 'left') + }, /*#__PURE__*/React.createElement(Icon, { + name: "chevronLeft", + size: 14 + })), /*#__PURE__*/React.createElement("button", { + className: "image-thumb-action", + title: "Nach rechts", + onClick: () => movePhoto(photo.id, 'right') + }, /*#__PURE__*/React.createElement(Icon, { + name: "chevronRight", + size: 14 + })), /*#__PURE__*/React.createElement("button", { + className: "image-thumb-action", + title: "KI-Retusche", + onClick: () => setShowRetusche(photo.id) + }, /*#__PURE__*/React.createElement(Icon, { + name: "sparkles", + size: 14 + })), /*#__PURE__*/React.createElement("button", { + className: "image-thumb-action danger", + title: "Loeschen", + onClick: () => setDeleteConfirm(photo.id) + }, /*#__PURE__*/React.createElement(Icon, { + name: "trash", + size: 14 + })))))))), lightbox !== null && photos[lightbox] && /*#__PURE__*/React.createElement("div", { + className: "lightbox", + onClick: () => setLightbox(null) + }, /*#__PURE__*/React.createElement("button", { + className: "lightbox-close", + onClick: () => setLightbox(null) + }, /*#__PURE__*/React.createElement(Icon, { + name: "close", + size: 24 + })), photos.length > 1 && /*#__PURE__*/React.createElement("button", { + className: "lightbox-nav prev", + onClick: e => { + e.stopPropagation(); + setLightbox(lightbox === 0 ? photos.length - 1 : lightbox - 1); + } + }, /*#__PURE__*/React.createElement(Icon, { + name: "chevronLeft", + size: 24 + })), /*#__PURE__*/React.createElement("div", { + className: "lightbox-image", + style: { + width: '70vw', + height: '60vh', + display: 'flex', + alignItems: 'center', + justifyContent: 'center' + }, + onClick: e => e.stopPropagation() + }, /*#__PURE__*/React.createElement(Icon, { + name: "image", + size: 120, + style: { + color: 'var(--color-text-muted)' + } + })), photos.length > 1 && /*#__PURE__*/React.createElement("button", { + className: "lightbox-nav next", + onClick: e => { + e.stopPropagation(); + setLightbox(lightbox === photos.length - 1 ? 0 : lightbox + 1); + } + }, /*#__PURE__*/React.createElement(Icon, { + name: "chevronRight", + size: 24 + })), /*#__PURE__*/React.createElement("div", { + className: "lightbox-info", + onClick: e => e.stopPropagation() + }, /*#__PURE__*/React.createElement("div", { + style: { + fontSize: 'var(--font-size-lg)', + fontWeight: 'var(--font-weight-semibold)' + } + }, "Foto ", lightbox + 1, " von ", photos.length), /*#__PURE__*/React.createElement("div", { + style: { + fontSize: 'var(--font-size-sm)', + opacity: 0.7 + } + }, catLabel(photos[lightbox].category), photos[lightbox].isMain ? ' · Hauptfoto' : ''))), showRetusche && /*#__PURE__*/React.createElement("div", { + className: "modal-overlay", + onClick: () => setShowRetusche(null) + }, /*#__PURE__*/React.createElement("div", { + className: "modal", + onClick: e => e.stopPropagation() + }, /*#__PURE__*/React.createElement("div", { + className: "modal-header" + }, /*#__PURE__*/React.createElement("h3", { + style: { + fontSize: 'var(--font-size-lg)', + fontWeight: 'var(--font-weight-semibold)' + } + }, /*#__PURE__*/React.createElement(Icon, { + name: "sparkles", + size: 20 + }), " KI-Bildretusche"), /*#__PURE__*/React.createElement("button", { + className: "btn btn-ghost btn-sm", + onClick: () => setShowRetusche(null) + }, /*#__PURE__*/React.createElement(Icon, { + name: "close", + size: 20 + }))), /*#__PURE__*/React.createElement("div", { + className: "modal-body" + }, /*#__PURE__*/React.createElement("p", { + style: { + fontSize: 'var(--font-size-sm)', + color: 'var(--color-text-secondary)', + marginBottom: 'var(--space-4)' + } + }, "Waehlen Sie eine Retusche-Option. Verarbeitung via OpenRouter Flux.1-Pro."), /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + flexDirection: 'column', + gap: 'var(--space-3)' + } + }, [{ + id: 'bg', + icon: 'image', + label: 'Hintergrund entfernen', + desc: 'Ersetzt Hintergrund durch neutrale Farbe' + }, { + id: 'reflections', + icon: 'sparkles', + label: 'Spiegelungen retuschieren', + desc: 'Reduziert Reflexionen auf der Fahrzeugoberflaeche' + }, { + id: 'brightness', + icon: 'sun', + label: 'Helligkeit optimieren', + desc: 'Passt Belichtung und Kontrast an' + }].map(opt => /*#__PURE__*/React.createElement("div", { + key: opt.id, + className: `retusche-option ${retuscheOption === opt.id ? 'selected' : ''}`, + onClick: () => setRetuscheOption(opt.id) + }, /*#__PURE__*/React.createElement("div", { + className: "retusche-option-icon" + }, /*#__PURE__*/React.createElement(Icon, { + name: opt.icon, + size: 20 + })), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + style: { + fontWeight: 'var(--font-weight-medium)' + } + }, opt.label), /*#__PURE__*/React.createElement("div", { + style: { + fontSize: 'var(--font-size-xs)', + color: 'var(--color-text-muted)' + } + }, opt.desc)))))), /*#__PURE__*/React.createElement("div", { + className: "modal-footer" + }, /*#__PURE__*/React.createElement(Button, { + variant: "secondary", + onClick: () => setShowRetusche(null) + }, "Abbrechen"), /*#__PURE__*/React.createElement(Button, { + variant: "primary", + icon: "sparkles", + disabled: !retuscheOption || retuscheLoading, + onClick: handleRetusche + }, retuscheLoading ? 'Verarbeite...' : 'Retusche starten')))), deleteConfirm && /*#__PURE__*/React.createElement("div", { + className: "modal-overlay", + onClick: () => setDeleteConfirm(null) + }, /*#__PURE__*/React.createElement("div", { + className: "modal", + onClick: e => e.stopPropagation(), + style: { + maxWidth: 400 + } + }, /*#__PURE__*/React.createElement("div", { + className: "modal-header" + }, /*#__PURE__*/React.createElement("h3", { + style: { + fontSize: 'var(--font-size-lg)' + } + }, "Foto loeschen?")), /*#__PURE__*/React.createElement("div", { + className: "modal-body" + }, /*#__PURE__*/React.createElement("p", { + style: { + fontSize: 'var(--font-size-sm)' + } + }, "Foto wirklich loeschen? Nicht rueckgaengig machbar.")), /*#__PURE__*/React.createElement("div", { + className: "modal-footer" + }, /*#__PURE__*/React.createElement(Button, { + variant: "secondary", + onClick: () => setDeleteConfirm(null) + }, "Abbrechen"), /*#__PURE__*/React.createElement(Button, { + variant: "danger", + icon: "trash", + onClick: () => deletePhoto(deleteConfirm) + }, "Loeschen"))))); +}; + +// ============ SIDEBAR + TOPBAR ============ +const Sidebar = ({ + route, + navigate, + role +}) => { + const navItems = [{ + section: 'nav.main', + items: [{ + id: '/dashboard', + icon: 'dashboard', + label: 'nav.dashboard', + roles: ['admin', 'verkaeufer', 'buchhaltung'] + }, { + id: '/fahrzeuge', + icon: 'truck', + label: 'nav.fahrzeuge', + roles: ['admin', 'verkaeufer', 'buchhaltung'] + }, { + id: '/kontakte', + icon: 'contacts', + label: 'nav.kontakte', + roles: ['admin', 'verkaeufer', 'buchhaltung'] + }, { + id: '/verkauf', + icon: 'sale', + label: 'nav.verkauf', + roles: ['admin', 'verkaeufer', 'buchhaltung'] + }] + }, { + section: 'nav.ki', + items: [{ + id: '/ki-copilot', + icon: 'ai', + label: 'nav.ki-copilot', + roles: ['admin', 'verkaeufer', 'buchhaltung'] + }] + }, { + section: 'nav.verwaltung', + items: [{ + id: '/einstellungen', + icon: 'settings', + label: 'nav.einstellungen', + roles: ['admin'] + }] + }]; + const isActive = id => route === id || id !== '/dashboard' && route.startsWith(id); + return /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement("div", { + className: "sidebar-overlay", + onClick: () => closeSidebar() + }), /*#__PURE__*/React.createElement("aside", { + className: "sidebar", + role: "navigation" + }, /*#__PURE__*/React.createElement("div", { + className: "sidebar-header" + }, /*#__PURE__*/React.createElement("div", { + className: "sidebar-logo" + }, "NF"), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + className: "sidebar-title" + }, "Nutzfahrzeug-ERP"), /*#__PURE__*/React.createElement("div", { + className: "sidebar-subtitle" + }, "Handelsverwaltung"))), /*#__PURE__*/React.createElement("nav", { + className: "sidebar-nav" + }, navItems.map((section, si) => /*#__PURE__*/React.createElement("div", { + key: si, + className: "sidebar-nav-section" + }, /*#__PURE__*/React.createElement("div", { + className: "sidebar-nav-label" + }, t(section.section)), section.items.map(item => item.roles.includes(role) ? /*#__PURE__*/React.createElement("a", { + key: item.id, + href: `#${item.id}`, + className: `sidebar-nav-item ${isActive(item.id) ? 'active' : ''}`, + onClick: () => closeSidebar() + }, /*#__PURE__*/React.createElement(Icon, { + name: item.icon, + size: 18 + }), /*#__PURE__*/React.createElement("span", null, t(item.label))) : null)))), /*#__PURE__*/React.createElement("div", { + className: "sidebar-footer" + }, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + alignItems: 'center', + gap: 'var(--space-3)', + padding: 'var(--space-2) var(--space-3)' + } + }, /*#__PURE__*/React.createElement(Avatar, { + name: "Max Mustermann" + }), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + style: { + fontSize: 'var(--font-size-sm)', + fontWeight: 'var(--font-weight-medium)' + } + }, "Max Mustermann"), /*#__PURE__*/React.createElement("div", { + style: { + fontSize: 'var(--font-size-xs)', + color: 'var(--color-text-muted)' + } + }, role === 'admin' ? 'Administrator' : role === 'verkaeufer' ? 'Verkaeufer' : 'Buchhaltung')))))); +}; +const Topbar = ({ + route, + role, + setRole, + navigate +}) => { + const [showProfile, setShowProfile] = useState(false); + const routeLabels = { + '/dashboard': 'nav.dashboard', + '/fahrzeuge': 'nav.fahrzeuge', + '/fahrzeuge/neu': 'nav.fahrzeuge.neu', + '/kontakte': 'nav.kontakte', + '/verkauf': 'nav.verkauf', + '/ki-copilot': 'nav.ki-copilot', + '/einstellungen': 'nav.einstellungen' + }; + const currentLabel = routeLabels[route] || routeLabels[route.split('/').slice(0, 2).join('/')] || 'nav.dashboard'; + return /*#__PURE__*/React.createElement("header", { + className: "topbar" + }, /*#__PURE__*/React.createElement("button", { + className: "mobile-menu-btn", + onClick: toggleSidebar + }, /*#__PURE__*/React.createElement(Icon, { + name: "menu", + size: 24 + })), /*#__PURE__*/React.createElement("div", { + className: "topbar-breadcrumb" + }, /*#__PURE__*/React.createElement("span", null, t('nav.main')), /*#__PURE__*/React.createElement(Icon, { + name: "chevronRight", + size: 14 + }), /*#__PURE__*/React.createElement("span", { + className: "current" + }, t(currentLabel))), /*#__PURE__*/React.createElement("div", { + className: "topbar-actions" + }, /*#__PURE__*/React.createElement("div", { + className: "lang-switcher", + style: { + display: 'flex', + gap: 'var(--space-1)' + } + }, /*#__PURE__*/React.createElement("button", { + className: `btn btn-ghost btn-sm ${currentLang === 'de' ? 'active' : ''}`, + onClick: () => setLang('de'), + style: { + fontWeight: currentLang === 'de' ? 'bold' : 'normal' + } + }, "DE"), /*#__PURE__*/React.createElement("button", { + className: `btn btn-ghost btn-sm ${currentLang === 'en' ? 'active' : ''}`, + onClick: () => setLang('en'), + style: { + fontWeight: currentLang === 'en' ? 'bold' : 'normal' + } + }, "EN")), /*#__PURE__*/React.createElement("button", { + className: "btn btn-ghost btn-sm", + onClick: toggleDarkMode + }, /*#__PURE__*/React.createElement(Icon, { + name: darkMode ? 'sun' : 'moon', + size: 18 + })), /*#__PURE__*/React.createElement("button", { + className: "btn btn-ghost btn-sm" + }, /*#__PURE__*/React.createElement(Icon, { + name: "bell", + size: 18 + })), /*#__PURE__*/React.createElement("div", { + style: { + position: 'relative' + } + }, /*#__PURE__*/React.createElement("button", { + className: "btn btn-ghost btn-sm", + onClick: () => setShowProfile(!showProfile), + style: { + gap: 'var(--space-2)' + } + }, /*#__PURE__*/React.createElement(Avatar, { + name: "Max Mustermann" + }), /*#__PURE__*/React.createElement(Icon, { + name: "chevronDown", + size: 14 + })), showProfile && /*#__PURE__*/React.createElement("div", { + style: { + position: 'absolute', + right: 0, + top: '100%', + marginTop: 'var(--space-2)', + background: 'var(--color-surface)', + border: '1px solid var(--color-border)', + borderRadius: 'var(--radius-lg)', + boxShadow: 'var(--shadow-lg)', + minWidth: 200, + zIndex: 'var(--z-dropdown)', + overflow: 'hidden' + } + }, /*#__PURE__*/React.createElement("div", { + style: { + padding: 'var(--space-3) var(--space-4)', + borderBottom: '1px solid var(--color-border)' + } + }, /*#__PURE__*/React.createElement("div", { + style: { + fontWeight: 'var(--font-weight-semibold)', + fontSize: 'var(--font-size-sm)' + } + }, "Max Mustermann"), /*#__PURE__*/React.createElement("div", { + style: { + fontSize: 'var(--font-size-xs)', + color: 'var(--color-text-muted)' + } + }, "max@nf-handel.de")), /*#__PURE__*/React.createElement("div", { + style: { + padding: 'var(--space-3) var(--space-4)' + } + }, /*#__PURE__*/React.createElement("div", { + className: "label" + }, "Rolle"), /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + gap: 'var(--space-1)', + marginTop: 'var(--space-2)' + } + }, ['admin', 'verkaeufer', 'buchhaltung'].map(r => /*#__PURE__*/React.createElement("button", { + key: r, + className: `btn btn-sm ${role === r ? 'btn-primary' : 'btn-secondary'}`, + onClick: () => { + setRole(r); + setShowProfile(false); + }, + style: { + fontSize: 'var(--font-size-xs)' + } + }, r === 'admin' ? 'Admin' : r === 'verkaeufer' ? 'Verkaeufer' : 'Buchhaltung')))), /*#__PURE__*/React.createElement("button", { + className: "btn btn-ghost", + style: { + width: '100%', + justifyContent: 'flex-start', + borderRadius: 0 + }, + onClick: () => navigate('/einstellungen') + }, /*#__PURE__*/React.createElement(Icon, { + name: "settings", + size: 16 + }), " ", t('nav.einstellungen')))))); +}; + +// ============ MOCK DATA ============ +const mockVehicles = [{ + id: 1, + marke: 'Mercedes-Benz', + modell: 'Actros 1845 LS', + fin: 'WDB9066351L123456', + baujahr: 2019, + erstzulassung: '2019-03-15', + kmStand: 150000, + betriebsstunden: null, + leistungKw: 330, + leistungPs: 449, + kraftstoff: 'Diesel', + getriebe: 'Automatik', + farbe: 'Weiss', + zustand: 'Gebraucht', + standort: 'Muenchen', + preis: 45000, + verfuegbarkeit: 'verfuegbar', + mobiledeStatus: 'gelistet', + typ: 'lkw', + hsn: '0911', + tsn: 'AAM', + egTyp: 'e1*2007/46*0514*12', + lkwTyp: 'Sattelzugmaschine', + aufbau: '3-Achs Sattelzug', + abgasnorm: 'Euro 6', + bereifung: '315/70 R22.5', + achsen: '3', + laenge: 6150, + breite: 2500, + hoehe: 3950, + leergewicht: 8500, + Gesamtgewicht: 19000, + hubraum: 14801, + vorbesitzer: 1, + unfallschaeden: false, + tuev: '03.2027', + serviceIntervall: 150000, + letzterService: '01.2026', + beschreibung: 'Top gepflegter Actros, Euro 6, 1. Hand', + lkwBordgeraet: true, + lkwHubwerk: false, + lkwLadebordwand: false, + lkwKlima: true, + lkwSchlafplatz: true, + lkwHydraulik: false, + anhaengelast: 40000, + kuppellast: 15000 +}, { + id: 2, + marke: 'MAN', + modell: 'TGL 12.180', + fin: 'WMAUYYT1XPA123456', + baujahr: 2018, + erstzulassung: '2018-06-20', + kmStand: 120000, + betriebsstunden: null, + leistungKw: 132, + leistungPs: 180, + kraftstoff: 'Diesel', + getriebe: 'Manuell', + farbe: 'Blau', + zustand: 'Gebraucht', + standort: 'Muenchen', + preis: 29500, + verfuegbarkeit: 'verfuegbar', + mobiledeStatus: 'gelistet', + typ: 'lkw', + hsn: '0846', + tsn: 'ABJ', + lkwTyp: 'Kastenwagen', + aufbau: 'Kuehlkoffer', + abgasnorm: 'Euro 6', + bereifung: '265/70 R19.5', + achsen: '2', + laenge: 7200, + breite: 2100, + hoehe: 2900, + leergewicht: 4500, + Gesamtgewicht: 12000, + hubraum: 4880, + vorbesitzer: 2, + unfallschaeden: false, + tuev: '06.2026', + serviceIntervall: 100000, + letzterService: '10.2025', + beschreibung: 'MAN TGL mit Kuehlkoffer, tempiert bis +2°C', + lkwBordgeraet: false, + lkwHubwerk: false, + lkwLadebordwand: true, + lkwKlima: true, + lkwSchlafplatz: false, + lkwHydraulik: false, + anhaengelast: 8000, + kuppellast: 750 +}, { + id: 3, + marke: 'BMW', + modell: 'X5 xDrive30d', + fin: 'WBAJA9C50K8123456', + baujahr: 2023, + erstzulassung: '2023-05-20', + kmStand: 25000, + betriebsstunden: null, + leistungKw: 195, + leistungPs: 265, + kraftstoff: 'Diesel', + getriebe: 'Automatik', + farbe: 'Schwarz Metallic', + zustand: 'Jahreswagen', + standort: 'Muenchen', + preis: 52000, + verfuegbarkeit: 'verfuegbar', + mobiledeStatus: 'gelistet', + typ: 'pkw', + hsn: '0511', + tsn: 'CZ1', + egTyp: 'e1*2007/46*1812*18', + pkwKlasse: 'Oberklasse', + pkwKarosserie: 'SUV', + pkwTueren: '5', + pkwSitze: '5', + pkwHubraum: 2993, + pkwAntrieb: 'Allrad', + pkwVerbrauch: '7.2', + pkwCo2: 189, + pkwUmwelt: 'gruen', + pkwReifen: '275/45 R20', + pkwAusstattung: ['Klimaautomatik', 'Navigation', 'Tempomat', 'Sitzheizung', 'LED-Matrix', 'Head-Up-Display'], + abgasnorm: 'Euro 6', + vorbesitzer: 1, + unfallschaeden: false, + tuev: '05.2025', + serviceIntervall: 30000, + letzterService: '03.2026', + laenge: 4922, + breite: 2004, + hoehe: 1776, + leergewicht: 2095, + Gesamtgewicht: 2670, + beschreibung: 'BMW X5 xDrive30d, Jahreswagen, M-Sportpaket' +}, { + id: 4, + marke: 'Volkswagen', + modell: 'Golf 8 2.0 TDI', + fin: 'WVWZZZ1KZ8W123456', + baujahr: 2022, + erstzulassung: '2022-03-10', + kmStand: 45000, + betriebsstunden: null, + leistungKw: 147, + leistungPs: 200, + kraftstoff: 'Diesel', + getriebe: 'DSG', + farbe: 'Grau', + zustand: 'Gebraucht', + standort: 'Muenchen', + preis: 28000, + verfuegbarkeit: 'verfuegbar', + mobiledeStatus: 'gelistet', + typ: 'pkw', + hsn: '0600', + tsn: 'BMR', + pkwKlasse: 'Kompaktklasse', + pkwKarosserie: 'Hatchback', + pkwTueren: '5', + pkwSitze: '5', + pkwHubraum: 1968, + pkwAntrieb: 'Front', + pkwVerbrauch: '5.1', + pkwCo2: 134, + pkwUmwelt: 'gruen', + pkwReifen: '225/45 R17', + pkwAusstattung: ['Klimaautomatik', 'Navigation', 'Tempomat', 'Spurhalteassistent'], + abgasnorm: 'Euro 6', + vorbesitzer: 1, + unfallschaeden: false, + tuev: '03.2024', + serviceIntervall: 30000, + letzterService: '01.2026', + laenge: 4284, + breite: 1789, + hoehe: 1456, + leergewicht: 1420, + Gesamtgewicht: 1910, + beschreibung: 'VW Golf 8 2.0 TDI DSG, Style' +}, { + id: 5, + marke: 'Liebherr', + modell: 'R 926 Crawler', + fin: 'LIR92620201234567', + baujahr: 2020, + erstzulassung: null, + kmStand: null, + betriebsstunden: 3200, + leistungKw: 150, + leistungPs: 204, + kraftstoff: 'Diesel', + getriebe: 'Hydrostat', + farbe: 'Gelb', + zustand: 'Gebraucht', + standort: 'Berlin', + preis: 89000, + verfuegbarkeit: 'verfuegbar', + mobiledeStatus: 'nicht_gelistet', + typ: 'baumaschine', + art: 'Bagger', + aufbau: 'Hydraulikbagger 26t', + bsEinheit: 'h', + abgasnorm: 'Euro 5', + vorbesitzer: 1, + unfallschaeden: false, + beschreibung: 'Liebherr R 926, 26t Raupenbagger' +}, { + id: 6, + marke: 'Toyota', + modell: '8FBE20 Elektrostapler', + fin: 'TOY8FBE20220123456', + baujahr: 2022, + erstzulassung: null, + kmStand: null, + betriebsstunden: 1850, + leistungKw: 4.5, + leistungPs: 6, + kraftstoff: 'Elektro', + getriebe: 'Stufenlos', + farbe: 'Orange', + zustand: 'Gebraucht', + standort: 'Berlin', + preis: 18500, + verfuegbarkeit: 'verfuegbar', + mobiledeStatus: 'nicht_gelistet', + typ: 'stapler', + abgasnorm: 'Keine', + staplerTrag: 2000, + staplerHubhoehe: 4500, + staplerBauhoehe: 2230, + staplerMast: 'Dreisteg', + staplerAntrieb: 'Elektro', + staplerBatterieKwh: 12.5, + staplerBatterieTyp: 'Lithium-Ion', + staplerReifen: 'Superelastik', + staplerLastschwerpunkt: 500, + staplerFahrkomponente: 'Stapler', + beschreibung: 'Toyota 8FBE20 Elektro-Gabelstapler, 2t' +}, { + id: 7, + marke: 'Scania', + modell: 'R 500 Highline', + fin: 'SCNR5002019123456', + baujahr: 2019, + erstzulassung: '2019-08-05', + kmStand: 210000, + betriebsstunden: null, + leistungKw: 368, + leistungPs: 500, + kraftstoff: 'Diesel', + getriebe: 'Automatik', + farbe: 'Rot', + zustand: 'Gebraucht', + standort: 'Muenchen', + preis: 38000, + verfuegbarkeit: 'verfuegbar', + mobiledeStatus: 'fehler', + typ: 'lkw', + hsn: '0856', + tsn: 'CKL', + lkwTyp: 'Sattelzugmaschine', + aufbau: '2-Achs Sattelzug', + abgasnorm: 'Euro 6', + bereifung: '315/70 R22.5', + achsen: '2', + laenge: 5800, + breite: 2500, + hoehe: 3800, + leergewicht: 7500, + Gesamtgewicht: 18000, + hubraum: 16400, + vorbesitzer: 2, + unfallschaeden: true, + tuev: '08.2026', + lkwBordgeraet: true, + lkwKlima: true, + lkwSchlafplatz: true, + anhaengelast: 40000, + kuppellast: 15000, + beschreibung: 'Scania R 500 Highline, V8, G410 Retarder' +}, { + id: 8, + marke: 'Linde', + modell: 'H25D Dieselsappler', + fin: 'LINH25D20211234567', + baujahr: 2021, + erstzulassung: null, + kmStand: null, + betriebsstunden: 3200, + leistungKw: 36, + leistungPs: 49, + kraftstoff: 'Diesel', + getriebe: 'Stufenlos', + farbe: 'Gelb', + zustand: 'Gebraucht', + standort: 'Koeln', + preis: 28000, + verfuegbarkeit: 'verfuegbar', + mobiledeStatus: 'nicht_gelistet', + typ: 'stapler', + abgasnorm: 'Euro 5', + staplerTrag: 2500, + staplerHubhoehe: 3000, + staplerBauhoehe: 1990, + staplerMast: 'Zweisteg', + staplerAntrieb: 'Diesel', + staplerBatterieKwh: null, + staplerBatterieTyp: null, + staplerReifen: 'Vollgummi', + staplerLastschwerpunkt: 500, + staplerFahrkomponente: 'Stapler', + beschreibung: 'Linde H25D Dieselstapler, 2.5t' +}]; +const mockContactsKaeufer = [{ + id: 1, + firmenname: 'Mueller Transport GmbH', + ansprechpartner: 'Thomas Mueller', + email: 't.mueller@mueller-transport.de', + telefon: '+49 89 1234567', + land: 'Deutschland', + ustId: 'DE123456789', + ustStatus: 'geprueft', + rolle: 'kaeufer', + adresse: 'Ludwigstrasse 45, 80336 Muenchen' +}, { + id: 2, + firmenname: 'Bauer Bauunternehmen GmbH', + ansprechpartner: 'Klaus Bauer', + email: 'k.bauer@bauer-bau.de', + telefon: '+49 30 9876543', + land: 'Deutschland', + ustId: 'DE987654321', + ustStatus: 'geprueft', + rolle: 'kaeufer', + adresse: 'Alexanderplatz 5, 10178 Berlin' +}, { + id: 4, + firmenname: 'Van den Berg Logistics B.V.', + ansprechpartner: 'Jan van den Berg', + email: 'j.vandenberg@vdberg.nl', + telefon: '+31 20 123 4567', + land: 'Niederlande', + ustId: 'NL123456789B01', + ustStatus: 'manuell_best', + rolle: 'kaeufer', + adresse: 'Keizersgracht 100, 1015 Amsterdam' +}]; +const mockContactsVerkaeufer = [{ + id: 3, + firmenname: 'TransLog AG', + ansprechpartner: 'Peter Schneider', + email: 'p.schneider@translog.ch', + telefon: '+41 44 555 1234', + land: 'Schweiz', + ustId: '', + ustStatus: 'ungeprueft', + rolle: 'verkaeufer', + adresse: 'Bahnhofstrasse 12, 8001 Zuerich' +}, { + id: 5, + firmenname: 'Schmidt Baumaschinen GmbH', + ansprechpartner: 'Andrea Schmidt', + email: 'a.schmidt@schmidt-baumaschinen.de', + telefon: '+49 221 555 7890', + land: 'Deutschland', + ustId: 'DE555444333', + ustStatus: 'geprueft', + rolle: 'beides', + adresse: 'Hohe Strasse 30, 50667 Koeln' +}]; +const statusBadge = s => { + const m = { + verfuegbar: { + v: 'success', + l: t('fb.verfuegbar') + }, + reserviert: { + v: 'warning', + l: t('fb.reserviert') + }, + verkauft: { + v: 'neutral', + l: t('fb.verkauft') + } + }; + const c = m[s] || m.verfuegbar; + return /*#__PURE__*/React.createElement(Badge, { + variant: c.v + }, c.l); +}; +const mobiledeBadge = s => { + const m = { + gelistet: { + v: 'success', + l: t('fb.gelistet') + }, + nicht_gelistet: { + v: 'neutral', + l: t('fb.nicht_gelistet') + }, + fehler: { + v: 'error', + l: t('fb.fehler') + }, + entfernt: { + v: 'neutral', + l: 'Entfernt' + } + }; + const c = m[s] || m.nicht_gelistet; + return /*#__PURE__*/React.createElement(Badge, { + variant: c.v + }, c.l); +}; +const typIcon = typ => typ === 'baumaschine' ? 'wrench' : typ === 'pkw' ? 'car' : typ === 'stapler' ? 'forklift' : 'truck'; +const typLabel = typ => typ === 'lkw' ? 'LKW' : typ === 'baumaschine' ? 'Baumaschine' : typ === 'pkw' ? 'PKW' : typ === 'stapler' ? 'Stapler' : 'Transporter'; + +// ============ DASHBOARD (v4 configurable) ============ +const DashboardView = ({ + navigate, + role +}) => { + const [widgets, setWidgets] = useState(() => { + const saved = localStorage.getItem('erp-dashboard-widgets'); + if (saved) try { + return JSON.parse(saved); + } catch (e) {} + return { + kpis: true, + quickActions: true, + activities: true, + tasks: true, + topVehicles: true + }; + }); + const [showConfig, setShowConfig] = useState(false); + const saveWidgets = w => { + setWidgets(w); + localStorage.setItem('erp-dashboard-widgets', JSON.stringify(w)); + }; + const toggleWidget = key => saveWidgets({ + ...widgets, + [key]: !widgets[key] + }); + const kpis = [{ + label: 'dash.fahrzeuge_im_bestand', + value: '52', + trend: '+5 diesen Monat', + trendDir: 'up', + icon: 'truck', + color: 'primary' + }, { + label: 'dash.verkaufe_diesen_monat', + value: '14', + trend: '+20% vs. Vormonat', + trendDir: 'up', + icon: 'sale', + color: 'success' + }, { + label: 'dash.offene_tasks', + value: '8', + trend: '3 ueberfaellig', + trendDir: 'down', + icon: 'clock', + color: 'warning' + }, { + label: 'dash.mobilede_sync', + value: '35/52', + trend: '17 nicht gelistet', + trendDir: 'down', + icon: 'sync', + color: 'info' + }]; + const recentActivities = [{ + type: 'sale', + text: 'Mercedes Actros an Mueller GmbH verkauft', + time: 'vor 2 Std' + }, { + type: 'add', + text: 'Neues Fahrzeug: BMW X5 xDrive30d (PKW)', + time: 'vor 4 Std' + }, { + type: 'add', + text: 'Neuer Stapler: Toyota 8FBE20 Elektrostapler', + time: 'vor 5 Std' + }, { + type: 'sync', + text: 'mobile.de Sync: 5 Fahrzeuge aktualisiert', + time: 'vor 6 Std' + }, { + type: 'edit', + text: 'Preis aktualisiert: MAN TGL - 32.000 -> 29.500', + time: 'vor 1 Tag' + }]; + const upcomingTasks = [{ + task: 'USt-IdNr.-Pruefung fuer Mueller GmbH (EU-Ausland)', + due: '15.07.2026', + priority: 'high' + }, { + task: 'Kaufvertrag: Volvo FH16 an Bauer GmbH', + due: '16.07.2026', + priority: 'high' + }, { + task: 'DATEV-Export fuer Juni 2026', + due: '20.07.2026', + priority: 'medium' + }, { + task: 'Fahrzeugfotos nachretuschieren (3 Fahrzeuge)', + due: '22.07.2026', + priority: 'low' + }]; + return /*#__PURE__*/React.createElement("div", { + style: { + position: 'relative' + } + }, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 'var(--space-6)', + flexWrap: 'wrap', + gap: 'var(--space-4)' + } + }, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h1", { + style: { + fontSize: 'var(--font-size-2xl)', + fontWeight: 'var(--font-weight-bold)' + } + }, t('dash.title')), /*#__PURE__*/React.createElement("p", { + style: { + color: 'var(--color-text-secondary)', + fontSize: 'var(--font-size-sm)', + marginTop: 'var(--space-1)' + } + }, "Willkommen zurueck, Max!")), /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + gap: 'var(--space-2)' + } + }, /*#__PURE__*/React.createElement(Button, { + variant: "ghost", + icon: "config", + onClick: () => setShowConfig(true), + title: "Dashboard konfigurieren" + }), /*#__PURE__*/React.createElement(Button, { + variant: "primary", + icon: "plus", + onClick: () => navigate('/fahrzeuge/neu'), + className: "hide-mobile" + }, t('dash.neues_fahrzeug')))), widgets.kpis && /*#__PURE__*/React.createElement("div", { + className: "kpi-grid", + style: { + marginBottom: 'var(--space-6)' + } + }, kpis.map((k, i) => /*#__PURE__*/React.createElement(KpiCard, { + key: i, + ...k + }))), widgets.quickActions && /*#__PURE__*/React.createElement(Card, { + title: t('dash.schnellzugriffe'), + className: "hide-mobile", + style: { + marginBottom: 'var(--space-6)' + } + }, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + gap: 'var(--space-4)', + flexWrap: 'wrap' + } + }, /*#__PURE__*/React.createElement(Button, { + variant: "primary", + icon: "plus", + onClick: () => navigate('/fahrzeuge/neu') + }, t('dash.neues_fahrzeug')), /*#__PURE__*/React.createElement(Button, { + variant: "secondary", + icon: "sale", + onClick: () => navigate('/verkauf') + }, t('dash.neuer_verkauf')), /*#__PURE__*/React.createElement(Button, { + variant: "secondary", + icon: "ai", + onClick: () => navigate('/ki-copilot') + }, t('dash.ki_copilot')), /*#__PURE__*/React.createElement(Button, { + variant: "secondary", + icon: "calendar", + onClick: () => navigate('/verkauf') + }, "Verkaufskalender"))), /*#__PURE__*/React.createElement("div", { + className: "two-col", + style: { + marginBottom: 'var(--space-6)' + } + }, widgets.activities && /*#__PURE__*/React.createElement(Card, { + title: t('dash.letzte_aktivitaeten') + }, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + flexDirection: 'column', + gap: 'var(--space-4)' + } + }, recentActivities.map((act, i) => /*#__PURE__*/React.createElement("div", { + key: i, + style: { + display: 'flex', + gap: 'var(--space-3)', + alignItems: 'flex-start' + } + }, /*#__PURE__*/React.createElement("div", { + style: { + width: 32, + height: 32, + borderRadius: 'var(--radius-md)', + flexShrink: 0, + background: act.type === 'sale' ? 'var(--color-success-light)' : act.type === 'add' ? 'var(--color-primary-light)' : act.type === 'sync' ? 'var(--color-info-light)' : 'var(--color-warning-light)', + color: act.type === 'sale' ? 'var(--color-success)' : act.type === 'add' ? 'var(--color-primary)' : act.type === 'sync' ? 'var(--color-info)' : 'var(--color-warning)', + display: 'flex', + alignItems: 'center', + justifyContent: 'center' + } + }, /*#__PURE__*/React.createElement(Icon, { + name: act.type === 'sale' ? 'sale' : act.type === 'add' ? 'plus' : act.type === 'sync' ? 'sync' : 'edit', + size: 16 + })), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + style: { + fontSize: 'var(--font-size-sm)', + fontWeight: 'var(--font-weight-medium)' + } + }, act.text), /*#__PURE__*/React.createElement("div", { + style: { + fontSize: 'var(--font-size-xs)', + color: 'var(--color-text-muted)' + } + }, act.time)))))), widgets.tasks && /*#__PURE__*/React.createElement(Card, { + title: t('dash.bevorstehende_tasks') + }, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + flexDirection: 'column', + gap: 'var(--space-3)' + } + }, upcomingTasks.map((task, i) => /*#__PURE__*/React.createElement("div", { + key: i, + style: { + display: 'flex', + alignItems: 'center', + gap: 'var(--space-3)', + padding: 'var(--space-3)', + borderRadius: 'var(--radius-md)', + border: '1px solid var(--color-border)' + } + }, /*#__PURE__*/React.createElement(Badge, { + variant: task.priority === 'high' ? 'error' : task.priority === 'medium' ? 'warning' : 'neutral' + }, task.priority === 'high' ? 'Hoch' : task.priority === 'medium' ? 'Mittel' : 'Niedrig'), /*#__PURE__*/React.createElement("div", { + style: { + flex: 1, + fontSize: 'var(--font-size-sm)' + } + }, task.task), /*#__PURE__*/React.createElement("div", { + style: { + fontSize: 'var(--font-size-xs)', + color: 'var(--color-text-muted)', + whiteSpace: 'nowrap' + } + }, /*#__PURE__*/React.createElement(Icon, { + name: "calendar", + size: 14 + }), " ", task.due)))))), widgets.topVehicles && /*#__PURE__*/React.createElement(Card, { + title: t('dash.top_fahrzeuge') + }, /*#__PURE__*/React.createElement("table", { + className: "data-table" + }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", null, "Marke"), /*#__PURE__*/React.createElement("th", null, "FIN"), /*#__PURE__*/React.createElement("th", null, "Anfragen"), /*#__PURE__*/React.createElement("th", null, "Preis"))), /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", { + onClick: () => navigate('/fahrzeug/1'), + style: { + cursor: 'pointer' + } + }, /*#__PURE__*/React.createElement("td", null, "Mercedes Actros 2019"), /*#__PURE__*/React.createElement("td", { + style: { + fontFamily: 'var(--font-mono)', + fontSize: 'var(--font-size-xs)' + } + }, "WDB9066351L123456"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "primary" + }, "24")), /*#__PURE__*/React.createElement("td", null, "45.000")), /*#__PURE__*/React.createElement("tr", { + onClick: () => navigate('/fahrzeug/3'), + style: { + cursor: 'pointer' + } + }, /*#__PURE__*/React.createElement("td", null, "BMW X5 xDrive30d"), /*#__PURE__*/React.createElement("td", { + style: { + fontFamily: 'var(--font-mono)', + fontSize: 'var(--font-size-xs)' + } + }, "WBAJA9C50K8123456"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "primary" + }, "18")), /*#__PURE__*/React.createElement("td", null, "52.000")), /*#__PURE__*/React.createElement("tr", { + onClick: () => navigate('/fahrzeug/5'), + style: { + cursor: 'pointer' + } + }, /*#__PURE__*/React.createElement("td", null, "Liebherr R 926"), /*#__PURE__*/React.createElement("td", { + style: { + fontFamily: 'var(--font-mono)', + fontSize: 'var(--font-size-xs)' + } + }, "LIR92620201234567"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "primary" + }, "12")), /*#__PURE__*/React.createElement("td", null, "89.000"))))), showConfig && /*#__PURE__*/React.createElement("div", { + className: "modal-overlay", + onClick: () => setShowConfig(false) + }, /*#__PURE__*/React.createElement("div", { + className: "modal", + onClick: e => e.stopPropagation() + }, /*#__PURE__*/React.createElement("div", { + className: "modal-header" + }, /*#__PURE__*/React.createElement("h3", { + style: { + fontSize: 'var(--font-size-lg)', + fontWeight: 'var(--font-weight-semibold)' + } + }, /*#__PURE__*/React.createElement(Icon, { + name: "config", + size: 20 + }), " Dashboard konfigurieren"), /*#__PURE__*/React.createElement("button", { + className: "btn btn-ghost btn-sm", + onClick: () => setShowConfig(false) + }, /*#__PURE__*/React.createElement(Icon, { + name: "close", + size: 20 + }))), /*#__PURE__*/React.createElement("div", { + className: "modal-body" + }, /*#__PURE__*/React.createElement("p", { + style: { + fontSize: 'var(--font-size-sm)', + color: 'var(--color-text-secondary)', + marginBottom: 'var(--space-4)' + } + }, "Widgets ein-/ausblenden. Konfiguration wird pro Benutzer gespeichert."), [{ + key: 'kpis', + label: 'KPI-Kennzahlen' + }, { + key: 'quickActions', + label: 'Schnellzugriffe' + }, { + key: 'activities', + label: 'Letzte Aktivitaeten' + }, { + key: 'tasks', + label: 'Bevorstehende Tasks' + }, { + key: 'topVehicles', + label: 'Top-Fahrzeuge' + }].map(item => /*#__PURE__*/React.createElement("div", { + key: item.key, + className: "config-item" + }, /*#__PURE__*/React.createElement("span", { + className: "config-item-label" + }, item.label), /*#__PURE__*/React.createElement("div", { + className: `toggle ${widgets[item.key] ? 'active' : ''}`, + onClick: () => toggleWidget(item.key) + })))), /*#__PURE__*/React.createElement("div", { + className: "modal-footer" + }, /*#__PURE__*/React.createElement(Button, { + variant: "primary", + onClick: () => setShowConfig(false) + }, "Fertig"))))); +}; + +// ============ FAHRZEUG LISTE ============ +const FahrzeugListe = ({ + navigate, + role +}) => { + const [search, setSearch] = useState(''); + const [filterType, setFilterType] = useState('alle'); + const [filterStatus, setFilterStatus] = useState('alle'); + const [sortBy, setSortBy] = useState('marke'); + const [sortDir, setSortDir] = useState('asc'); + const [view, setView] = useState('table'); + const [page, setPage] = useState(1); + const perPage = 10; + const filtered = useMemo(() => { + let r = mockVehicles.filter(v => { + const ms = !search || v.marke.toLowerCase().includes(search.toLowerCase()) || v.modell.toLowerCase().includes(search.toLowerCase()) || v.fin.toLowerCase().includes(search.toLowerCase()) || (v.hsn || '').includes(search); + const mt = filterType === 'alle' || v.typ === filterType; + const mst = filterStatus === 'alle' || v.verfuegbarkeit === filterStatus; + return ms && mt && mst; + }); + r.sort((a, b) => { + const av = a[sortBy] || '', + bv = b[sortBy] || ''; + if (typeof av === 'number') return sortDir === 'asc' ? av - bv : bv - av; + return sortDir === 'asc' ? String(av).localeCompare(String(bv)) : String(bv).localeCompare(String(av)); + }); + return r; + }, [search, filterType, filterStatus, sortBy, sortDir]); + const totalPages = Math.ceil(filtered.length / perPage); + const pageData = filtered.slice((page - 1) * perPage, page * perPage); + const handleSort = col => { + if (sortBy === col) setSortDir(sortDir === 'asc' ? 'desc' : 'asc');else { + setSortBy(col); + setSortDir('asc'); + } + }; + return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 'var(--space-6)', + flexWrap: 'wrap', + gap: 'var(--space-4)' + } + }, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h1", { + style: { + fontSize: 'var(--font-size-2xl)', + fontWeight: 'var(--font-weight-bold)' + } + }, t('fb.title')), /*#__PURE__*/React.createElement("p", { + style: { + color: 'var(--color-text-secondary)', + fontSize: 'var(--font-size-sm)' + } + }, filtered.length, " ", t('common.eintraege'))), /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + gap: 'var(--space-2)', + alignItems: 'center' + } + }, /*#__PURE__*/React.createElement(ViewToggle, { + view: view, + onChange: setView + }), /*#__PURE__*/React.createElement(Button, { + variant: "secondary", + icon: "download", + className: "hide-mobile" + }, "Export"), role !== 'buchhaltung' && /*#__PURE__*/React.createElement(Button, { + variant: "primary", + icon: "plus", + onClick: () => navigate('/fahrzeuge/neu') + }, t('fb.add_new')))), /*#__PURE__*/React.createElement(Card, { + style: { + marginBottom: 'var(--space-4)' + } + }, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + gap: 'var(--space-4)', + flexWrap: 'wrap', + alignItems: 'flex-end' + } + }, /*#__PURE__*/React.createElement("div", { + style: { + flex: '1 1 300px' + } + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Suche (Marke, Modell, FIN, HSN)"), /*#__PURE__*/React.createElement("div", { + style: { + position: 'relative' + } + }, /*#__PURE__*/React.createElement(Icon, { + name: "search", + size: 16, + style: { + position: 'absolute', + left: 'var(--space-3)', + top: '50%', + transform: 'translateY(-50%)', + color: 'var(--color-text-muted)' + } + }), /*#__PURE__*/React.createElement("input", { + className: "input", + style: { + paddingLeft: 'var(--space-8)' + }, + placeholder: t('fb.suche'), + value: search, + onChange: e => { + setSearch(e.target.value); + setPage(1); + } + }))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Typ"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: filterType, + onChange: e => { + setFilterType(e.target.value); + setPage(1); + } + }, /*#__PURE__*/React.createElement("option", { + value: "alle" + }, "Alle"), /*#__PURE__*/React.createElement("option", { + value: "lkw" + }, "LKW"), /*#__PURE__*/React.createElement("option", { + value: "baumaschine" + }, "Baumaschine"), /*#__PURE__*/React.createElement("option", { + value: "pkw" + }, "PKW"), /*#__PURE__*/React.createElement("option", { + value: "stapler" + }, "Stapler"), /*#__PURE__*/React.createElement("option", { + value: "transporter" + }, "Transporter"))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Status"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: filterStatus, + onChange: e => { + setFilterStatus(e.target.value); + setPage(1); + } + }, /*#__PURE__*/React.createElement("option", { + value: "alle" + }, "Alle"), /*#__PURE__*/React.createElement("option", { + value: "verfuegbar" + }, "Verfuegbar"), /*#__PURE__*/React.createElement("option", { + value: "reserviert" + }, "Reserviert"), /*#__PURE__*/React.createElement("option", { + value: "verkauft" + }, "Verkauft"))), /*#__PURE__*/React.createElement(Button, { + variant: "ghost", + icon: "close", + onClick: () => { + setSearch(''); + setFilterType('alle'); + setFilterStatus('alle'); + } + }, "Reset"))), pageData.length === 0 ? /*#__PURE__*/React.createElement(Card, null, /*#__PURE__*/React.createElement(EmptyState, { + icon: "truck", + title: "Keine Fahrzeuge", + text: "Legen Sie Ihr erstes Fahrzeug an.", + action: role !== 'buchhaltung' && /*#__PURE__*/React.createElement(Button, { + variant: "primary", + icon: "plus", + onClick: () => navigate('/fahrzeuge/neu') + }, "Fahrzeug hinzufuegen") + })) : view === 'table' ? /*#__PURE__*/React.createElement(Card, null, /*#__PURE__*/React.createElement("div", { + style: { + overflowX: 'auto' + } + }, /*#__PURE__*/React.createElement("table", { + className: "data-table" + }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", { + className: sortBy === 'marke' ? 'sorted' : '', + onClick: () => handleSort('marke') + }, "Marke"), /*#__PURE__*/React.createElement("th", null, "Modell"), /*#__PURE__*/React.createElement("th", null, "FIN"), /*#__PURE__*/React.createElement("th", null, "Baujahr"), /*#__PURE__*/React.createElement("th", { + className: "hide-mobile" + }, "KM/h"), /*#__PURE__*/React.createElement("th", { + className: sortBy === 'preis' ? 'sorted' : '', + onClick: () => handleSort('preis') + }, "Preis"), /*#__PURE__*/React.createElement("th", null, "Typ"), /*#__PURE__*/React.createElement("th", null, "Status"), /*#__PURE__*/React.createElement("th", { + className: "hide-mobile" + }, "mobile.de"), /*#__PURE__*/React.createElement("th", null, "Aktion"))), /*#__PURE__*/React.createElement("tbody", null, pageData.map(v => /*#__PURE__*/React.createElement("tr", { + key: v.id, + onClick: () => navigate('/fahrzeug/' + v.id), + style: { + cursor: 'pointer' + } + }, /*#__PURE__*/React.createElement("td", { + style: { + fontWeight: 'var(--font-weight-semibold)' + } + }, v.marke), /*#__PURE__*/React.createElement("td", null, v.modell), /*#__PURE__*/React.createElement("td", { + style: { + fontFamily: 'var(--font-mono)', + fontSize: 'var(--font-size-xs)' + } + }, v.fin), /*#__PURE__*/React.createElement("td", null, v.baujahr), /*#__PURE__*/React.createElement("td", { + className: "hide-mobile" + }, v.kmStand ? formatNumber(v.kmStand) + ' km' : v.betriebsstunden ? formatNumber(v.betriebsstunden) + ' h' : '-'), /*#__PURE__*/React.createElement("td", { + style: { + fontWeight: 'var(--font-weight-semibold)' + } + }, formatPrice(v.preis)), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "info" + }, typLabel(v.typ))), /*#__PURE__*/React.createElement("td", null, statusBadge(v.verfuegbarkeit)), /*#__PURE__*/React.createElement("td", { + className: "hide-mobile" + }, mobiledeBadge(v.mobiledeStatus)), /*#__PURE__*/React.createElement("td", { + onClick: e => e.stopPropagation() + }, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + gap: 'var(--space-1)' + } + }, /*#__PURE__*/React.createElement("button", { + className: "btn btn-ghost btn-sm", + onClick: () => navigate('/fahrzeug/' + v.id) + }, /*#__PURE__*/React.createElement(Icon, { + name: "eye", + size: 16 + })), role !== 'buchhaltung' && /*#__PURE__*/React.createElement("button", { + className: "btn btn-ghost btn-sm", + onClick: () => navigate('/fahrzeuge/neu?id=' + v.id) + }, /*#__PURE__*/React.createElement(Icon, { + name: "edit", + size: 16 + }))))))))), /*#__PURE__*/React.createElement("div", { + className: "pagination" + }, /*#__PURE__*/React.createElement("div", { + className: "pagination-info" + }, (page - 1) * perPage + 1, "-", Math.min(page * perPage, filtered.length), " von ", filtered.length), /*#__PURE__*/React.createElement("div", { + className: "pagination-controls" + }, /*#__PURE__*/React.createElement("button", { + className: "pagination-btn", + disabled: page === 1, + onClick: () => setPage(page - 1) + }, /*#__PURE__*/React.createElement(Icon, { + name: "chevronLeft", + size: 16 + })), Array.from({ + length: totalPages + }, (_, i) => i + 1).map(p => /*#__PURE__*/React.createElement("button", { + key: p, + className: `pagination-btn ${page === p ? 'active' : ''}`, + onClick: () => setPage(p) + }, p)), /*#__PURE__*/React.createElement("button", { + className: "pagination-btn", + disabled: page === totalPages, + onClick: () => setPage(page + 1) + }, /*#__PURE__*/React.createElement(Icon, { + name: "chevronRight", + size: 16 + }))))) : /*#__PURE__*/React.createElement("div", { + className: "card-grid" + }, filtered.map(v => /*#__PURE__*/React.createElement("div", { + key: v.id, + className: "vehicle-card", + onClick: () => navigate('/fahrzeug/' + v.id) + }, /*#__PURE__*/React.createElement("div", { + className: "vehicle-card-image" + }, /*#__PURE__*/React.createElement(Icon, { + name: typIcon(v.typ), + size: 48, + style: { + color: 'var(--color-text-muted)' + } + }), /*#__PURE__*/React.createElement("div", { + className: "card-status-badge" + }, statusBadge(v.verfuegbarkeit))), /*#__PURE__*/React.createElement("div", { + className: "vehicle-card-body" + }, /*#__PURE__*/React.createElement("div", { + className: "vehicle-card-title" + }, v.marke, " ", v.modell), /*#__PURE__*/React.createElement("div", { + className: "vehicle-card-subtitle" + }, "FIN: ", v.fin), /*#__PURE__*/React.createElement("div", { + className: "vehicle-card-info" + }, /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(Icon, { + name: "calendar", + size: 12 + }), " ", v.baujahr), /*#__PURE__*/React.createElement("span", null, /*#__PURE__*/React.createElement(Badge, { + variant: "info" + }, typLabel(v.typ)))), /*#__PURE__*/React.createElement("div", { + className: "vehicle-card-meta" + }, /*#__PURE__*/React.createElement("div", { + className: "vehicle-card-price" + }, formatPrice(v.preis)), mobiledeBadge(v.mobiledeStatus))))))); +}; + +// ============ FAHRZEUG DETAIL ============ +const FahrzeugDetail = ({ + id, + navigate, + role +}) => { + const [activeTab, setActiveTab] = useState('allgemein'); + const [photos, setPhotos] = useState([{ + id: 1, + category: 'aussen_front', + isMain: true + }, { + id: 2, + category: 'aussen_seite', + isMain: false + }, { + id: 3, + category: 'aussen_heck', + isMain: false + }, { + id: 4, + category: 'innen_armaturen', + isMain: false + }]); + const vehicle = mockVehicles.find(v => v.id === parseInt(id)); + if (!vehicle) return /*#__PURE__*/React.createElement(ErrorState, { + title: "Nicht gefunden", + text: "Fahrzeug existiert nicht.", + onRetry: () => navigate('/fahrzeuge') + }); + const tabs = [{ + id: 'allgemein', + label: 'Allgemein' + }, { + id: 'technisch', + label: 'Technisch' + }, { + id: 'abmessungen', + label: 'Abmessungen' + }, ...(vehicle.typ === 'baumaschine' ? [{ + id: 'baumaschine', + label: 'Baumaschine' + }] : []), ...(vehicle.typ === 'pkw' ? [{ + id: 'pkw', + label: 'PKW-Daten' + }] : []), ...(vehicle.typ === 'stapler' ? [{ + id: 'stapler', + label: 'Stapler-Daten' + }] : []), ...(vehicle.typ === 'lkw' ? [{ + id: 'lkw', + label: 'LKW-Daten' + }] : []), { + id: 'verkaufsinfo', + label: 'Verkaufsinfo' + }, { + id: 'dokumente', + label: 'Dokumente' + }, { + id: 'fotos', + label: 'Fotos' + }, { + id: 'mobilede', + label: 'mobile.de' + }]; + return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + alignItems: 'center', + gap: 'var(--space-4)', + marginBottom: 'var(--space-6)', + flexWrap: 'wrap' + } + }, /*#__PURE__*/React.createElement(Button, { + variant: "ghost", + icon: "chevronLeft", + onClick: () => navigate('/fahrzeuge') + }, t('fd.zurueck')), /*#__PURE__*/React.createElement("div", { + style: { + flex: 1 + } + }, /*#__PURE__*/React.createElement("h1", { + style: { + fontSize: 'var(--font-size-2xl)', + fontWeight: 'var(--font-weight-bold)' + } + }, vehicle.marke, " ", vehicle.modell), /*#__PURE__*/React.createElement("p", { + style: { + color: 'var(--color-text-secondary)', + fontSize: 'var(--font-size-sm)', + fontFamily: 'var(--font-mono)' + } + }, "FIN: ", vehicle.fin, " · HSN: ", vehicle.hsn || '-', " · TSN: ", vehicle.tsn || '-')), role !== 'buchhaltung' && /*#__PURE__*/React.createElement(Button, { + variant: "secondary", + icon: "edit", + onClick: () => navigate('/fahrzeuge/neu?id=' + vehicle.id) + }, "Bearbeiten"), role !== 'buchhaltung' && /*#__PURE__*/React.createElement(Button, { + variant: "primary", + icon: "sale", + onClick: () => navigate('/verkauf?vehicle=' + vehicle.id) + }, "Verkaufen")), /*#__PURE__*/React.createElement("div", { + className: "tabs" + }, tabs.map(tab => /*#__PURE__*/React.createElement("div", { + key: tab.id, + className: `tab ${activeTab === tab.id ? 'active' : ''}`, + onClick: () => setActiveTab(tab.id) + }, tab.label))), activeTab === 'allgemein' && /*#__PURE__*/React.createElement(Card, { + title: "Allgemein" + }, /*#__PURE__*/React.createElement("div", { + className: "info-grid" + }, /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Marke"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.marke)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Modell"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.modell)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "FIN"), /*#__PURE__*/React.createElement("div", { + className: "info-value", + style: { + fontFamily: 'var(--font-mono)' + } + }, vehicle.fin)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Baujahr"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.baujahr)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Erstzulassung"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.erstzulassung ? formatDate(vehicle.erstzulassung) : '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Farbe"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.farbe)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Zustand"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.zustand)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Standort"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.standort)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "HSN ", /*#__PURE__*/React.createElement(ZBRef, { + field: "(2.1)" + })), /*#__PURE__*/React.createElement("div", { + className: "info-value", + style: { + fontFamily: 'var(--font-mono)' + } + }, vehicle.hsn || '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "TSN ", /*#__PURE__*/React.createElement(ZBRef, { + field: "(2.2)" + })), /*#__PURE__*/React.createElement("div", { + className: "info-value", + style: { + fontFamily: 'var(--font-mono)' + } + }, vehicle.tsn || '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "EG-Typgenehmigung ", /*#__PURE__*/React.createElement(ZBRef, { + field: "K" + })), /*#__PURE__*/React.createElement("div", { + className: "info-value", + style: { + fontFamily: 'var(--font-mono)', + fontSize: 'var(--font-size-xs)' + } + }, vehicle.egTyp || '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Vorbesitzer"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.vorbesitzer || '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Unfallschaeden"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.unfallschaeden ? /*#__PURE__*/React.createElement(Badge, { + variant: "error" + }, "Ja") : /*#__PURE__*/React.createElement(Badge, { + variant: "success" + }, "Nein"))), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "TUeV/AU"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.tuev || '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Letzter Service"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.letzterService || '-'))), vehicle.beschreibung && /*#__PURE__*/React.createElement("div", { + style: { + marginTop: 'var(--space-4)', + paddingTop: 'var(--space-4)', + borderTop: '1px solid var(--color-border)' + } + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Beschreibung"), /*#__PURE__*/React.createElement("p", { + style: { + marginTop: 'var(--space-2)', + fontSize: 'var(--font-size-sm)' + } + }, vehicle.beschreibung))), activeTab === 'technisch' && /*#__PURE__*/React.createElement(Card, { + title: "Technische Daten" + }, /*#__PURE__*/React.createElement("div", { + className: "info-grid" + }, /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Leistung (kW) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "P.2" + })), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.leistungKw, " kW")), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Leistung (PS)"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.leistungPs, " PS")), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Kraftstoff ", /*#__PURE__*/React.createElement(ZBRef, { + field: "P.3" + })), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.kraftstoff)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Getriebe"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.getriebe)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Hubraum (ccm) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "P.1" + })), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.hubraum || '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Abgasnorm"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.abgasnorm || '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "KM-Stand"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.kmStand ? formatNumber(vehicle.kmStand) + ' km' : '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Betriebsstunden"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.betriebsstunden ? formatNumber(vehicle.betriebsstunden) + ' h' : '-')))), activeTab === 'abmessungen' && /*#__PURE__*/React.createElement(Card, { + title: "Abmessungen & Gewichte" + }, /*#__PURE__*/React.createElement("div", { + className: "info-grid" + }, /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Laenge (mm) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "(18)" + })), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.laenge || '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Breite (mm) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "(19)" + })), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.breite || '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Hoehe (mm) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "(20)" + })), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.hoehe || '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Leergewicht (kg) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "G" + })), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.leergewicht || '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Gesamtgewicht (kg) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "F.1" + })), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.Gesamtgewicht || '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Achsen ", /*#__PURE__*/React.createElement(ZBRef, { + field: "L" + })), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.achsen || '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Bereifung ", /*#__PURE__*/React.createElement(ZBRef, { + field: "(15)" + })), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.bereifung || '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Anhaengelast ", /*#__PURE__*/React.createElement(ZBRef, { + field: "O.1" + })), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.anhaengelast ? formatNumber(vehicle.anhaengelast) + ' kg' : '-')))), activeTab === 'pkw' && vehicle.typ === 'pkw' && /*#__PURE__*/React.createElement(Card, { + title: "PKW-Daten" + }, /*#__PURE__*/React.createElement("div", { + className: "info-grid" + }, /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Fahrzeugklasse"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.pkwKlasse)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Karosserie"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.pkwKarosserie)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Tueren"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.pkwTueren)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Sitzplaetze ", /*#__PURE__*/React.createElement(ZBRef, { + field: "S.1" + })), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.pkwSitze)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Antriebsart"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.pkwAntrieb)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Verbrauch (l/100km)"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.pkwVerbrauch)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "CO2 (g/km) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "V.7" + })), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.pkwCo2)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Umweltplakette"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, /*#__PURE__*/React.createElement(Badge, { + variant: vehicle.pkwUmwelt === 'gruen' ? 'success' : 'warning' + }, vehicle.pkwUmwelt)))), vehicle.pkwAusstattung && /*#__PURE__*/React.createElement("div", { + style: { + marginTop: 'var(--space-4)', + paddingTop: 'var(--space-4)', + borderTop: '1px solid var(--color-border)' + } + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Ausstattung"), /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + flexWrap: 'wrap', + gap: 'var(--space-2)', + marginTop: 'var(--space-2)' + } + }, vehicle.pkwAusstattung.map((a, i) => /*#__PURE__*/React.createElement(Badge, { + key: i, + variant: "primary" + }, a))))), activeTab === 'lkw' && vehicle.typ === 'lkw' && /*#__PURE__*/React.createElement(Card, { + title: "LKW-Daten" + }, /*#__PURE__*/React.createElement("div", { + className: "info-grid" + }, /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "LKW-Typ"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.lkwTyp)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Aufbau"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.aufbau || '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Bordgeraet"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.lkwBordgeraet ? /*#__PURE__*/React.createElement(Badge, { + variant: "success" + }, "Ja") : /*#__PURE__*/React.createElement(Badge, { + variant: "neutral" + }, "Nein"))), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Hubwerk"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.lkwHubwerk ? /*#__PURE__*/React.createElement(Badge, { + variant: "success" + }, "Ja") : /*#__PURE__*/React.createElement(Badge, { + variant: "neutral" + }, "Nein"))), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Ladebordwand"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.lkwLadebordwand ? /*#__PURE__*/React.createElement(Badge, { + variant: "success" + }, "Ja") : /*#__PURE__*/React.createElement(Badge, { + variant: "neutral" + }, "Nein"))), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Klimaanlage"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.lkwKlima ? /*#__PURE__*/React.createElement(Badge, { + variant: "success" + }, "Ja") : /*#__PURE__*/React.createElement(Badge, { + variant: "neutral" + }, "Nein"))), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Schlafplatz"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.lkwSchlafplatz ? /*#__PURE__*/React.createElement(Badge, { + variant: "success" + }, "Ja") : /*#__PURE__*/React.createElement(Badge, { + variant: "neutral" + }, "Nein"))), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Hydraulik"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.lkwHydraulik ? /*#__PURE__*/React.createElement(Badge, { + variant: "success" + }, "Ja") : /*#__PURE__*/React.createElement(Badge, { + variant: "neutral" + }, "Nein"))), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Anhaengelast (kg)"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.anhaengelast ? formatNumber(vehicle.anhaengelast) : '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Kuppelast (kg)"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.kuppellast ? formatNumber(vehicle.kuppellast) : '-')))), activeTab === 'baumaschine' && vehicle.typ === 'baumaschine' && /*#__PURE__*/React.createElement(Card, { + title: "Baumaschinen-Daten" + }, /*#__PURE__*/React.createElement("div", { + className: "info-grid" + }, /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Art"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.art)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Betriebsstunden"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.betriebsstunden ? formatNumber(vehicle.betriebsstunden) + ' h' : '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Aufbau"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.aufbau || '-')))), activeTab === 'stapler' && vehicle.typ === 'stapler' && /*#__PURE__*/React.createElement(Card, { + title: "Stapler-Daten" + }, /*#__PURE__*/React.createElement("div", { + className: "info-grid" + }, /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Tragfaehigkeit (kg)"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.staplerTrag)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Hubhoehe (mm)"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.staplerHubhoehe)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Bauhoehe (mm)"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.staplerBauhoehe)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Masttyp"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.staplerMast)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Antrieb"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.staplerAntrieb)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Batterie"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.staplerBatterieKwh ? vehicle.staplerBatterieKwh + ' kWh' : '-')), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Reifenart"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.staplerReifen)))), activeTab === 'verkaufsinfo' && /*#__PURE__*/React.createElement(Card, { + title: "Verkaufsinfo" + }, /*#__PURE__*/React.createElement("div", { + className: "info-grid" + }, /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Preis"), /*#__PURE__*/React.createElement("div", { + className: "info-value", + style: { + fontSize: 'var(--font-size-xl)', + color: 'var(--color-primary)' + } + }, formatPrice(vehicle.preis))), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Status"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, statusBadge(vehicle.verfuegbarkeit))), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Standort"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, vehicle.standort)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Typ"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, typLabel(vehicle.typ))))), activeTab === 'dokumente' && /*#__PURE__*/React.createElement(Card, { + title: "Dokumente" + }, /*#__PURE__*/React.createElement("table", { + className: "data-table" + }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", null, "Dateiname"), /*#__PURE__*/React.createElement("th", null, "Kategorie"), /*#__PURE__*/React.createElement("th", null, "Aktion"))), /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "ZB_I_Fahrzeugschein.pdf"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "info" + }, "ZB I")), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("button", { + className: "btn btn-ghost btn-sm" + }, /*#__PURE__*/React.createElement(Icon, { + name: "download", + size: 16 + })))), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "ZB_II_Fahrzeugbrief.pdf"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "info" + }, "ZB II")), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("button", { + className: "btn btn-ghost btn-sm" + }, /*#__PURE__*/React.createElement(Icon, { + name: "download", + size: 16 + })))), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "Kaufvertrag.pdf"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "primary" + }, "Vertrag")), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("button", { + className: "btn btn-ghost btn-sm" + }, /*#__PURE__*/React.createElement(Icon, { + name: "download", + size: 16 + }))))))), activeTab === 'fotos' && /*#__PURE__*/React.createElement(Card, { + title: "Fotos" + }, /*#__PURE__*/React.createElement(ImageManager, { + photos: photos, + setPhotos: setPhotos, + role: role + })), activeTab === 'mobilede' && /*#__PURE__*/React.createElement(Card, { + title: "mobile.de Status" + }, /*#__PURE__*/React.createElement("div", { + style: { + marginBottom: 'var(--space-4)' + } + }, mobiledeBadge(vehicle.mobiledeStatus)), vehicle.mobiledeStatus === 'fehler' && /*#__PURE__*/React.createElement("div", { + className: "warning-banner" + }, /*#__PURE__*/React.createElement(Icon, { + name: "alert", + size: 20, + className: "warning-banner-icon" + }), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("strong", null, "API Fehler:"), " Pflichtfeld fehlt.")), /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + gap: 'var(--space-2)', + flexWrap: 'wrap' + } + }, role !== 'buchhaltung' && /*#__PURE__*/React.createElement(Button, { + variant: "primary", + icon: "sync" + }, "Sync"), /*#__PURE__*/React.createElement(Button, { + variant: "secondary", + icon: "chart" + }, "Preisvergleich")))); +}; + +// ============ FAHRZEUG FORM (v4 tabbed) ============ +const FahrzeugForm = ({ + navigate, + editId +}) => { + const [typ, setTyp] = useState('lkw'); + const [errors, setErrors] = useState({}); + const [ocrLoading, setOcrLoading] = useState(false); + const [saving, setSaving] = useState(false); + const [photos, setPhotos] = useState([]); + const [activeFormTab, setActiveFormTab] = useState('allgemein'); + const editVehicle = editId ? mockVehicles.find(v => v.id === parseInt(editId)) : null; + const [form, setForm] = useState(editVehicle || { + marke: '', + modell: '', + fin: '', + baujahr: '', + erstzulassung: '', + kmStand: '', + betriebsstunden: '', + leistungKw: '', + leistungPs: '', + kraftstoff: 'Diesel', + getriebe: 'Manuell', + farbe: '', + zustand: 'Gebraucht', + standort: 'Muenchen', + preis: '', + hsn: '', + tsn: '', + egTyp: '', + hubraum: '', + abgasnorm: 'Euro 6', + vorbesitzer: '', + unfallschaeden: false, + tuev: '', + letzterService: '', + serviceIntervall: '', + laenge: '', + breite: '', + hoehe: '', + leergewicht: '', + Gesamtgewicht: '', + achsen: '', + bereifung: '', + anhaengelast: '', + kuppellast: '', + antriebsart: '', + verbrauch: '', + co2: '', + umweltplakette: 'gruen', + lkwTyp: '', + aufbau: '', + lkwBordgeraet: false, + lkwHubwerk: false, + lkwLadebordwand: false, + lkwKlima: false, + lkwSchlafplatz: false, + lkwHydraulik: false, + art: '', + bsEinheit: 'h', + pkwKlasse: '', + pkwKarosserie: '', + pkwTueren: '', + pkwSitze: '', + pkwHubraum: '', + pkwAntrieb: '', + pkwVerbrauch: '', + pkwCo2: '', + pkwUmwelt: 'gruen', + pkwReifen: '', + pkwAusstattung: [], + staplerTrag: '', + staplerHubhoehe: '', + staplerBauhoehe: '', + staplerMast: '', + staplerAntrieb: 'Elektro', + staplerBatterieKwh: '', + staplerBatterieTyp: '', + staplerReifen: 'Superelastik', + staplerLastschwerpunkt: '500', + staplerFahrkomponente: 'Stapler', + kaufpreis: '', + mwst: '19', + provision: '', + lagerkosten: '', + transportkosten: '', + beschreibung: '' + }); + const update = (f, v) => setForm({ + ...form, + [f]: v + }); + const validate = () => { + const e = {}; + if (!form.marke) e.marke = 'Pflicht'; + if (!form.modell) e.modell = 'Pflicht'; + if (!form.fin) e.fin = 'Pflicht';else if (form.fin.length !== 17) e.fin = '17 Zeichen'; + if (!form.baujahr) e.baujahr = 'Pflicht'; + if (!form.preis) e.preis = 'Pflicht'; + setErrors(e); + return Object.keys(e).length === 0; + }; + const handleSubmit = e => { + e.preventDefault(); + if (!validate()) return; + setSaving(true); + setTimeout(() => { + setSaving(false); + navigate('/fahrzeuge'); + }, 1000); + }; + const handleOcr = () => { + setOcrLoading(true); + setTimeout(() => { + setOcrLoading(false); + setForm({ + ...form, + marke: 'Mercedes-Benz', + modell: 'Actros 1845 LS', + fin: 'WDB9066351L123456', + baujahr: '2019', + erstzulassung: '2019-03-15', + leistungKw: '330', + kraftstoff: 'Diesel', + farbe: 'Weiss', + abgasnorm: 'Euro 6', + hsn: '0911', + tsn: 'AAM' + }); + }, 2000); + }; + const formTabs = [{ + id: 'allgemein', + label: 'Allgemein', + icon: 'tag' + }, { + id: 'technisch', + label: 'Technische Daten', + icon: 'wrench' + }, { + id: 'abmessungen', + label: 'Abmessungen', + icon: 'package' + }, ...(typ === 'pkw' ? [{ + id: 'pkw', + label: 'PKW', + icon: 'car' + }] : []), ...(typ === 'lkw' ? [{ + id: 'lkw', + label: 'LKW', + icon: 'truck' + }] : []), ...(typ === 'baumaschine' ? [{ + id: 'baumaschine', + label: 'Baumaschine', + icon: 'wrench' + }] : []), ...(typ === 'stapler' ? [{ + id: 'stapler', + label: 'Stapler', + icon: 'forklift' + }] : []), { + id: 'preise', + label: 'Preise & Kosten', + icon: 'euro' + }, { + id: 'bilder', + label: 'Bilder', + icon: 'image' + }, { + id: 'dokumente', + label: 'Dokumente', + icon: 'doc' + }, { + id: 'mobilede', + label: 'mobile.de', + icon: 'external' + }]; + return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + alignItems: 'center', + gap: 'var(--space-4)', + marginBottom: 'var(--space-6)' + } + }, /*#__PURE__*/React.createElement(Button, { + variant: "ghost", + icon: "chevronLeft", + onClick: () => navigate('/fahrzeuge') + }, t('fd.zurueck')), /*#__PURE__*/React.createElement("h1", { + style: { + fontSize: 'var(--font-size-2xl)', + fontWeight: 'var(--font-weight-bold)' + } + }, t(editId ? 'ff.titel_bearbeiten' : 'ff.titel_neu'))), /*#__PURE__*/React.createElement(Card, { + title: "Fahrzeugtyp", + style: { + marginBottom: 'var(--space-6)' + } + }, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + gap: 'var(--space-2)', + flexWrap: 'wrap' + } + }, ['lkw', 'baumaschine', 'pkw', 'stapler', 'transporter'].map(o => /*#__PURE__*/React.createElement("button", { + key: o, + type: "button", + className: `btn ${typ === o ? 'btn-primary' : 'btn-secondary'}`, + onClick: () => setTyp(o) + }, /*#__PURE__*/React.createElement(Icon, { + name: typIcon(o), + size: 16 + }), " ", typLabel(o))))), /*#__PURE__*/React.createElement(Card, { + title: t('ff.ocr_upload'), + style: { + marginBottom: 'var(--space-6)' + } + }, /*#__PURE__*/React.createElement("p", { + style: { + fontSize: 'var(--font-size-sm)', + color: 'var(--color-text-secondary)', + marginBottom: 'var(--space-4)' + } + }, t('ff.ocr_text')), /*#__PURE__*/React.createElement("div", { + className: "dropzone", + onClick: handleOcr + }, ocrLoading ? /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: 'var(--space-3)' + } + }, /*#__PURE__*/React.createElement("div", { + className: "spinner spinner-lg" + }), /*#__PURE__*/React.createElement("p", { + style: { + fontSize: 'var(--font-size-sm)' + } + }, "OCR laeuft... Qwen2.5-VL")) : /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + flexDirection: 'column', + alignItems: 'center', + gap: 'var(--space-2)' + } + }, /*#__PURE__*/React.createElement(Icon, { + name: "camera", + size: 48, + style: { + color: 'var(--color-text-muted)' + } + }), /*#__PURE__*/React.createElement("p", { + style: { + fontWeight: 'var(--font-weight-medium)' + } + }, "ZB I / ZB II hier klicken"), /*#__PURE__*/React.createElement(Button, { + variant: "primary", + size: "sm", + icon: "sparkles", + style: { + marginTop: 'var(--space-2)' + } + }, t('ff.ocr_ausloesen'))))), /*#__PURE__*/React.createElement("form", { + onSubmit: handleSubmit + }, /*#__PURE__*/React.createElement("div", { + className: "form-tabs" + }, formTabs.map(tab => /*#__PURE__*/React.createElement("div", { + key: tab.id, + className: `form-tab ${activeFormTab === tab.id ? 'active' : ''}`, + onClick: () => setActiveFormTab(tab.id) + }, /*#__PURE__*/React.createElement(Icon, { + name: tab.icon, + size: 16 + }), " ", tab.label))), activeFormTab === 'allgemein' && /*#__PURE__*/React.createElement(Card, { + title: "Allgemein" + }, /*#__PURE__*/React.createElement("div", { + className: "three-col" + }, /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Marke * ", /*#__PURE__*/React.createElement(ZBRef, { + field: "D.1" + })), /*#__PURE__*/React.createElement("input", { + className: `input ${errors.marke ? 'input-error' : ''}`, + value: form.marke, + onChange: e => update('marke', e.target.value) + }), errors.marke && /*#__PURE__*/React.createElement("div", { + className: "form-error" + }, errors.marke)), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Modell * ", /*#__PURE__*/React.createElement(ZBRef, { + field: "D.3" + })), /*#__PURE__*/React.createElement("input", { + className: `input ${errors.modell ? 'input-error' : ''}`, + value: form.modell, + onChange: e => update('modell', e.target.value) + }), errors.modell && /*#__PURE__*/React.createElement("div", { + className: "form-error" + }, errors.modell)), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "FIN * ", /*#__PURE__*/React.createElement(ZBRef, { + field: "E" + })), /*#__PURE__*/React.createElement("input", { + className: `input ${errors.fin ? 'input-error' : ''}`, + value: form.fin, + onChange: e => update('fin', e.target.value), + maxLength: 17, + style: { + fontFamily: 'var(--font-mono)' + } + }), errors.fin && /*#__PURE__*/React.createElement("div", { + className: "form-error" + }, errors.fin)), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Baujahr *"), /*#__PURE__*/React.createElement("input", { + className: `input ${errors.baujahr ? 'input-error' : ''}`, + type: "number", + value: form.baujahr, + onChange: e => update('baujahr', e.target.value) + }), errors.baujahr && /*#__PURE__*/React.createElement("div", { + className: "form-error" + }, errors.baujahr)), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Erstzulassung ", /*#__PURE__*/React.createElement(ZBRef, { + field: "B" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "date", + value: form.erstzulassung, + onChange: e => update('erstzulassung', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Farbe ", /*#__PURE__*/React.createElement(ZBRef, { + field: "R" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + value: form.farbe, + onChange: e => update('farbe', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Zustand"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.zustand, + onChange: e => update('zustand', e.target.value) + }, /*#__PURE__*/React.createElement("option", null, "Neu"), /*#__PURE__*/React.createElement("option", null, "Gebraucht"), /*#__PURE__*/React.createElement("option", null, "Jahreswagen"), /*#__PURE__*/React.createElement("option", null, "Unfallfahrzeug"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Standort"), /*#__PURE__*/React.createElement("input", { + className: "input", + value: form.standort, + onChange: e => update('standort', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "HSN ", /*#__PURE__*/React.createElement(ZBRef, { + field: "(2.1)" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + value: form.hsn, + onChange: e => update('hsn', e.target.value), + placeholder: "0911", + style: { + fontFamily: 'var(--font-mono)' + } + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "TSN ", /*#__PURE__*/React.createElement(ZBRef, { + field: "(2.2)" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + value: form.tsn, + onChange: e => update('tsn', e.target.value), + placeholder: "AAM", + style: { + fontFamily: 'var(--font-mono)' + } + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "EG-Typgenehmigung ", /*#__PURE__*/React.createElement(ZBRef, { + field: "K" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + value: form.egTyp, + onChange: e => update('egTyp', e.target.value), + style: { + fontFamily: 'var(--font-mono)', + fontSize: 'var(--font-size-xs)' + } + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Vorbesitzer"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.vorbesitzer, + onChange: e => update('vorbesitzer', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Unfallschaeden"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.unfallschaeden, + onChange: e => update('unfallschaeden', e.target.value === 'true') + }, /*#__PURE__*/React.createElement("option", { + value: "false" + }, "Nein"), /*#__PURE__*/React.createElement("option", { + value: "true" + }, "Ja"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "TUeV/AU gueltig bis"), /*#__PURE__*/React.createElement("input", { + className: "input", + value: form.tuev, + onChange: e => update('tuev', e.target.value), + placeholder: "03.2027" + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Letzter Service"), /*#__PURE__*/React.createElement("input", { + className: "input", + value: form.letzterService, + onChange: e => update('letzterService', e.target.value), + placeholder: "01.2026" + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Service-Intervall (km)"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.serviceIntervall, + onChange: e => update('serviceIntervall', e.target.value), + placeholder: "150000" + })))), activeFormTab === 'technisch' && /*#__PURE__*/React.createElement(Card, { + title: "Technische Daten" + }, /*#__PURE__*/React.createElement("div", { + className: "three-col" + }, /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Leistung (kW) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "P.2" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.leistungKw, + onChange: e => update('leistungKw', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Leistung (PS)"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.leistungPs, + onChange: e => update('leistungPs', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Hubraum (ccm) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "P.1" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.hubraum, + onChange: e => update('hubraum', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Kraftstoff ", /*#__PURE__*/React.createElement(ZBRef, { + field: "P.3" + })), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.kraftstoff, + onChange: e => update('kraftstoff', e.target.value) + }, /*#__PURE__*/React.createElement("option", null, "Diesel"), /*#__PURE__*/React.createElement("option", null, "Benzin"), /*#__PURE__*/React.createElement("option", null, "Elektro"), /*#__PURE__*/React.createElement("option", null, "Hybrid"), /*#__PURE__*/React.createElement("option", null, "Gas (CNG/LPG)"), /*#__PURE__*/React.createElement("option", null, "Wasserstoff"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Getriebe"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.getriebe, + onChange: e => update('getriebe', e.target.value) + }, /*#__PURE__*/React.createElement("option", null, "Manuell"), /*#__PURE__*/React.createElement("option", null, "Automatik"), /*#__PURE__*/React.createElement("option", null, "DSG"), /*#__PURE__*/React.createElement("option", null, "Hydrostat"), /*#__PURE__*/React.createElement("option", null, "Stufenlos"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Antriebsart"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.antriebsart, + onChange: e => update('antriebsart', e.target.value) + }, /*#__PURE__*/React.createElement("option", { + value: "" + }, "--"), /*#__PURE__*/React.createElement("option", null, "Frontantrieb"), /*#__PURE__*/React.createElement("option", null, "Heckantrieb"), /*#__PURE__*/React.createElement("option", null, "Allrad"), /*#__PURE__*/React.createElement("option", null, "4x4"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Abgasnorm"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.abgasnorm, + onChange: e => update('abgasnorm', e.target.value) + }, /*#__PURE__*/React.createElement("option", null, "Euro 6"), /*#__PURE__*/React.createElement("option", null, "Euro 5"), /*#__PURE__*/React.createElement("option", null, "Euro 4"), /*#__PURE__*/React.createElement("option", null, "Euro 3"), /*#__PURE__*/React.createElement("option", null, "Euro 2"), /*#__PURE__*/React.createElement("option", null, "Euro 1"), /*#__PURE__*/React.createElement("option", null, "Keine"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Verbrauch (l/100km)"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + step: "0.1", + value: form.verbrauch, + onChange: e => update('verbrauch', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "CO2 (g/km) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "V.7" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.co2, + onChange: e => update('co2', e.target.value) + })), (typ === 'lkw' || typ === 'transporter' || typ === 'pkw') && /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "KM-Stand"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.kmStand, + onChange: e => update('kmStand', e.target.value) + })), (typ === 'baumaschine' || typ === 'stapler') && /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Betriebsstunden"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.betriebsstunden, + onChange: e => update('betriebsstunden', e.target.value) + })))), activeFormTab === 'abmessungen' && /*#__PURE__*/React.createElement(Card, { + title: "Abmessungen & Gewichte" + }, /*#__PURE__*/React.createElement("div", { + className: "three-col" + }, /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Laenge (mm) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "(18)" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.laenge, + onChange: e => update('laenge', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Breite (mm) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "(19)" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.breite, + onChange: e => update('breite', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Hoehe (mm) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "(20)" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.hoehe, + onChange: e => update('hoehe', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Leergewicht (kg) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "G" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.leergewicht, + onChange: e => update('leergewicht', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Gesamtgewicht (kg) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "F.1" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.Gesamtgewicht, + onChange: e => update('Gesamtgewicht', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Achsen ", /*#__PURE__*/React.createElement(ZBRef, { + field: "L" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.achsen, + onChange: e => update('achsen', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Bereifung ", /*#__PURE__*/React.createElement(ZBRef, { + field: "(15)" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + value: form.bereifung, + onChange: e => update('bereifung', e.target.value), + placeholder: "315/70 R22.5" + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Anhaengelast (kg) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "O.1" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.anhaengelast, + onChange: e => update('anhaengelast', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Kuppelast (kg) ", /*#__PURE__*/React.createElement(ZBRef, { + field: "(13)" + })), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.kuppellast, + onChange: e => update('kuppellast', e.target.value) + })))), activeFormTab === 'pkw' && typ === 'pkw' && /*#__PURE__*/React.createElement(Card, { + title: "PKW-spezifische Daten" + }, /*#__PURE__*/React.createElement("div", { + className: "three-col" + }, /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Fahrzeugklasse ", /*#__PURE__*/React.createElement(ZBRef, { + field: "J" + })), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.pkwKlasse, + onChange: e => update('pkwKlasse', e.target.value) + }, /*#__PURE__*/React.createElement("option", { + value: "" + }, "--"), /*#__PURE__*/React.createElement("option", null, "Kleinwagen"), /*#__PURE__*/React.createElement("option", null, "Kompaktklasse"), /*#__PURE__*/React.createElement("option", null, "Mittelklasse"), /*#__PURE__*/React.createElement("option", null, "Oberklasse"), /*#__PURE__*/React.createElement("option", null, "Luxusklasse"), /*#__PURE__*/React.createElement("option", null, "Gelaendewagen"), /*#__PURE__*/React.createElement("option", null, "Van"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Karosserieform"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.pkwKarosserie, + onChange: e => update('pkwKarosserie', e.target.value) + }, /*#__PURE__*/React.createElement("option", { + value: "" + }, "--"), /*#__PURE__*/React.createElement("option", null, "Limousine"), /*#__PURE__*/React.createElement("option", null, "Kombi"), /*#__PURE__*/React.createElement("option", null, "Hatchback"), /*#__PURE__*/React.createElement("option", null, "Coupé"), /*#__PURE__*/React.createElement("option", null, "Cabrio"), /*#__PURE__*/React.createElement("option", null, "SUV"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Tueren"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.pkwTueren, + onChange: e => update('pkwTueren', e.target.value) + }, /*#__PURE__*/React.createElement("option", { + value: "" + }, "--"), /*#__PURE__*/React.createElement("option", null, "2"), /*#__PURE__*/React.createElement("option", null, "3"), /*#__PURE__*/React.createElement("option", null, "4"), /*#__PURE__*/React.createElement("option", null, "5"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Sitzplaetze ", /*#__PURE__*/React.createElement(ZBRef, { + field: "S.1" + })), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.pkwSitze, + onChange: e => update('pkwSitze', e.target.value) + }, /*#__PURE__*/React.createElement("option", { + value: "" + }, "--"), /*#__PURE__*/React.createElement("option", null, "2"), /*#__PURE__*/React.createElement("option", null, "4"), /*#__PURE__*/React.createElement("option", null, "5"), /*#__PURE__*/React.createElement("option", null, "7"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Hubraum (ccm)"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.pkwHubraum, + onChange: e => update('pkwHubraum', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Antriebsart"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.pkwAntrieb, + onChange: e => update('pkwAntrieb', e.target.value) + }, /*#__PURE__*/React.createElement("option", { + value: "" + }, "--"), /*#__PURE__*/React.createElement("option", null, "Frontantrieb"), /*#__PURE__*/React.createElement("option", null, "Heckantrieb"), /*#__PURE__*/React.createElement("option", null, "Allrad"), /*#__PURE__*/React.createElement("option", null, "4x4"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Verbrauch (l/100km)"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + step: "0.1", + value: form.pkwVerbrauch, + onChange: e => update('pkwVerbrauch', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "CO2 (g/km)"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.pkwCo2, + onChange: e => update('pkwCo2', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Umweltplakette"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.pkwUmwelt, + onChange: e => update('pkwUmwelt', e.target.value) + }, /*#__PURE__*/React.createElement("option", { + value: "gruen" + }, "Gruen"), /*#__PURE__*/React.createElement("option", { + value: "gelb" + }, "Gelb"), /*#__PURE__*/React.createElement("option", { + value: "rot" + }, "Rot"), /*#__PURE__*/React.createElement("option", { + value: "keine" + }, "Keine"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Reifengroesse"), /*#__PURE__*/React.createElement("input", { + className: "input", + value: form.pkwReifen, + onChange: e => update('pkwReifen', e.target.value), + placeholder: "275/45 R20" + })))), activeFormTab === 'lkw' && typ === 'lkw' && /*#__PURE__*/React.createElement(Card, { + title: "LKW-spezifische Daten" + }, /*#__PURE__*/React.createElement("div", { + className: "three-col" + }, /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "LKW-Typ"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.lkwTyp, + onChange: e => update('lkwTyp', e.target.value) + }, /*#__PURE__*/React.createElement("option", { + value: "" + }, "--"), /*#__PURE__*/React.createElement("option", null, "Sattelzugmaschine"), /*#__PURE__*/React.createElement("option", null, "Solo-LKW"), /*#__PURE__*/React.createElement("option", null, "Kastenwagen"), /*#__PURE__*/React.createElement("option", null, "Pritsche"), /*#__PURE__*/React.createElement("option", null, "Tieflader"), /*#__PURE__*/React.createElement("option", null, "Kipper"), /*#__PURE__*/React.createElement("option", null, "Silo"), /*#__PURE__*/React.createElement("option", null, "Kuehlwagen"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Aufbau"), /*#__PURE__*/React.createElement("input", { + className: "input", + value: form.aufbau, + onChange: e => update('aufbau', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Bordgeraet"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.lkwBordgeraet, + onChange: e => update('lkwBordgeraet', e.target.value === 'true') + }, /*#__PURE__*/React.createElement("option", { + value: "false" + }, "Nein"), /*#__PURE__*/React.createElement("option", { + value: "true" + }, "Ja"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Hubwerk"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.lkwHubwerk, + onChange: e => update('lkwHubwerk', e.target.value === 'true') + }, /*#__PURE__*/React.createElement("option", { + value: "false" + }, "Nein"), /*#__PURE__*/React.createElement("option", { + value: "true" + }, "Ja"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Ladebordwand"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.lkwLadebordwand, + onChange: e => update('lkwLadebordwand', e.target.value === 'true') + }, /*#__PURE__*/React.createElement("option", { + value: "false" + }, "Nein"), /*#__PURE__*/React.createElement("option", { + value: "true" + }, "Ja"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Klimaanlage"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.lkwKlima, + onChange: e => update('lkwKlima', e.target.value === 'true') + }, /*#__PURE__*/React.createElement("option", { + value: "false" + }, "Nein"), /*#__PURE__*/React.createElement("option", { + value: "true" + }, "Ja"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Schlafplatz"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.lkwSchlafplatz, + onChange: e => update('lkwSchlafplatz', e.target.value === 'true') + }, /*#__PURE__*/React.createElement("option", { + value: "false" + }, "Nein"), /*#__PURE__*/React.createElement("option", { + value: "true" + }, "Ja"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Hydraulische Anlage"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.lkwHydraulik, + onChange: e => update('lkwHydraulik', e.target.value === 'true') + }, /*#__PURE__*/React.createElement("option", { + value: "false" + }, "Nein"), /*#__PURE__*/React.createElement("option", { + value: "true" + }, "Ja"))))), activeFormTab === 'baumaschine' && typ === 'baumaschine' && /*#__PURE__*/React.createElement(Card, { + title: "Baumaschinen-spezifische Daten" + }, /*#__PURE__*/React.createElement("div", { + className: "three-col" + }, /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Art"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.art, + onChange: e => update('art', e.target.value) + }, /*#__PURE__*/React.createElement("option", { + value: "" + }, "--"), /*#__PURE__*/React.createElement("option", null, "Bagger"), /*#__PURE__*/React.createElement("option", null, "Radlader"), /*#__PURE__*/React.createElement("option", null, "Kran"), /*#__PURE__*/React.createElement("option", null, "Walze"), /*#__PURE__*/React.createElement("option", null, "Bulldozer"), /*#__PURE__*/React.createElement("option", null, "Teleskoplader"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Einheit"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.bsEinheit, + onChange: e => update('bsEinheit', e.target.value) + }, /*#__PURE__*/React.createElement("option", { + value: "h" + }, "Stunden (h)"), /*#__PURE__*/React.createElement("option", { + value: "min" + }, "Minuten (min)"))))), activeFormTab === 'stapler' && typ === 'stapler' && /*#__PURE__*/React.createElement(Card, { + title: "Stapler-spezifische Daten" + }, /*#__PURE__*/React.createElement("div", { + className: "three-col" + }, /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Tragfaehigkeit (kg)"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.staplerTrag, + onChange: e => update('staplerTrag', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Hubhoehe (mm)"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.staplerHubhoehe, + onChange: e => update('staplerHubhoehe', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Bauhoehe (mm)"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.staplerBauhoehe, + onChange: e => update('staplerBauhoehe', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Masttyp"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.staplerMast, + onChange: e => update('staplerMast', e.target.value) + }, /*#__PURE__*/React.createElement("option", { + value: "" + }, "--"), /*#__PURE__*/React.createElement("option", null, "Dreisteg"), /*#__PURE__*/React.createElement("option", null, "Zweisteg"), /*#__PURE__*/React.createElement("option", null, "Scherenmast"), /*#__PURE__*/React.createElement("option", null, "Teleskopmast"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Antriebsart"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.staplerAntrieb, + onChange: e => update('staplerAntrieb', e.target.value) + }, /*#__PURE__*/React.createElement("option", null, "Elektro"), /*#__PURE__*/React.createElement("option", null, "Diesel"), /*#__PURE__*/React.createElement("option", null, "Gas"), /*#__PURE__*/React.createElement("option", null, "Benzin"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Batteriekapazitaet (kWh)"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + step: "0.1", + value: form.staplerBatterieKwh, + onChange: e => update('staplerBatterieKwh', e.target.value), + disabled: form.staplerAntrieb !== 'Elektro' + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Batterietyp"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.staplerBatterieTyp, + onChange: e => update('staplerBatterieTyp', e.target.value), + disabled: form.staplerAntrieb !== 'Elektro' + }, /*#__PURE__*/React.createElement("option", { + value: "" + }, "--"), /*#__PURE__*/React.createElement("option", null, "Blei-Saeure"), /*#__PURE__*/React.createElement("option", null, "Lithium-Ion"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Reifenart"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.staplerReifen, + onChange: e => update('staplerReifen', e.target.value) + }, /*#__PURE__*/React.createElement("option", null, "Superelastik"), /*#__PURE__*/React.createElement("option", null, "Vollgummi"), /*#__PURE__*/React.createElement("option", null, "Luftreifen"), /*#__PURE__*/React.createElement("option", null, "Polyurethan"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Lastschwerpunkt (mm)"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.staplerLastschwerpunkt, + onChange: e => update('staplerLastschwerpunkt', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Fahrkomponente"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.staplerFahrkomponente, + onChange: e => update('staplerFahrkomponente', e.target.value) + }, /*#__PURE__*/React.createElement("option", null, "Stapler"), /*#__PURE__*/React.createElement("option", null, "Radlader"), /*#__PURE__*/React.createElement("option", null, "Teleskoplader"), /*#__PURE__*/React.createElement("option", null, "Hubwagen"), /*#__PURE__*/React.createElement("option", null, "Kommissionierer"))))), activeFormTab === 'preise' && /*#__PURE__*/React.createElement(Card, { + title: "Preise & Kosten" + }, /*#__PURE__*/React.createElement("div", { + className: "three-col" + }, /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Verkaufspreis (€) *"), /*#__PURE__*/React.createElement("input", { + className: `input ${errors.preis ? 'input-error' : ''}`, + type: "number", + value: form.preis, + onChange: e => update('preis', e.target.value) + }), errors.preis && /*#__PURE__*/React.createElement("div", { + className: "form-error" + }, errors.preis)), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Kaufpreis (€)"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.kaufpreis, + onChange: e => update('kaufpreis', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "MwSt-Satz"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: form.mwst, + onChange: e => update('mwst', e.target.value) + }, /*#__PURE__*/React.createElement("option", { + value: "19" + }, "19%"), /*#__PURE__*/React.createElement("option", { + value: "7" + }, "7%"), /*#__PURE__*/React.createElement("option", { + value: "0" + }, "0% (steuerfrei)"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Provision (€)"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.provision, + onChange: e => update('provision', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Lagerkosten (€/Monat)"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.lagerkosten, + onChange: e => update('lagerkosten', e.target.value) + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Transportkosten (€)"), /*#__PURE__*/React.createElement("input", { + className: "input", + type: "number", + value: form.transportkosten, + onChange: e => update('transportkosten', e.target.value) + })))), activeFormTab === 'bilder' && /*#__PURE__*/React.createElement(Card, { + title: "Fotos" + }, /*#__PURE__*/React.createElement(ImageManager, { + photos: photos, + setPhotos: setPhotos, + role: "admin" + })), activeFormTab === 'dokumente' && /*#__PURE__*/React.createElement(Card, { + title: "Dokumente" + }, /*#__PURE__*/React.createElement("div", { + className: "dropzone", + style: { + marginBottom: 'var(--space-4)' + } + }, /*#__PURE__*/React.createElement(Icon, { + name: "upload", + size: 48, + style: { + color: 'var(--color-text-muted)' + } + }), /*#__PURE__*/React.createElement("p", { + style: { + fontWeight: 'var(--font-weight-medium)' + } + }, "Dokumente hochladen"), /*#__PURE__*/React.createElement("p", { + style: { + fontSize: 'var(--font-size-xs)', + color: 'var(--color-text-muted)' + } + }, "ZB I, ZB II, TUeV, Vertrag, Rechnung · PDF/JPG · max 50 MB"), /*#__PURE__*/React.createElement("div", { + style: { + marginTop: 'var(--space-3)' + } + }, /*#__PURE__*/React.createElement("div", { + className: "file-input-wrapper" + }, /*#__PURE__*/React.createElement(Button, { + variant: "primary", + size: "sm", + icon: "doc" + }, "Datei auswaehlen"), /*#__PURE__*/React.createElement("input", { + type: "file", + multiple: true, + accept: ".pdf,image/*" + }))))), activeFormTab === 'mobilede' && /*#__PURE__*/React.createElement(Card, { + title: "mobile.de Listing" + }, /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Listing-Status"), /*#__PURE__*/React.createElement("select", { + className: "select" + }, /*#__PURE__*/React.createElement("option", null, "Entwurf"), /*#__PURE__*/React.createElement("option", null, "Gelistet"), /*#__PURE__*/React.createElement("option", null, "Nicht gelistet"))), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Beschreibung (fuer mobile.de)"), /*#__PURE__*/React.createElement("textarea", { + className: "textarea", + rows: 4, + value: form.beschreibung, + onChange: e => update('beschreibung', e.target.value), + placeholder: "Top gepflegter LKW, 1. Hand..." + }))), /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + gap: 'var(--space-3)', + justifyContent: 'flex-end', + marginTop: 'var(--space-6)' + } + }, /*#__PURE__*/React.createElement(Button, { + variant: "secondary", + onClick: () => navigate('/fahrzeuge') + }, t('ff.abbrechen')), /*#__PURE__*/React.createElement(Button, { + variant: "primary", + icon: saving ? undefined : 'check', + type: "submit", + disabled: saving + }, saving ? t('common.laden') : t('ff.speichern'))))); +}; + +// ============ KONTAKTE ============ +const KontakteListe = ({ + navigate, + role +}) => { + const [tab, setTab] = useState('kunden'); + const [search, setSearch] = useState(''); + const [view, setView] = useState('table'); + const data = tab === 'kunden' ? mockContactsKaeufer : mockContactsVerkaeufer; + const filtered = data.filter(c => !search || c.firmenname.toLowerCase().includes(search.toLowerCase()) || c.ansprechpartner.toLowerCase().includes(search.toLowerCase())); + const ustBadge = s => { + const m = { + geprueft: { + v: 'success', + l: t('kt.geprueft') + }, + ungeprueft: { + v: 'warning', + l: t('kt.ungeprueft') + }, + manuell_best: { + v: 'info', + l: t('kt.manuell_best') + } + }; + const c = m[s] || m.ungeprueft; + return /*#__PURE__*/React.createElement(Badge, { + variant: c.v + }, c.l); + }; + return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 'var(--space-6)', + flexWrap: 'wrap', + gap: 'var(--space-4)' + } + }, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h1", { + style: { + fontSize: 'var(--font-size-2xl)', + fontWeight: 'var(--font-weight-bold)' + } + }, t('kt.title')), /*#__PURE__*/React.createElement("p", { + style: { + color: 'var(--color-text-secondary)', + fontSize: 'var(--font-size-sm)' + } + }, filtered.length, " ", t('common.eintraege'))), /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + gap: 'var(--space-2)', + alignItems: 'center' + } + }, /*#__PURE__*/React.createElement(ViewToggle, { + view: view, + onChange: setView + }), role !== 'buchhaltung' && /*#__PURE__*/React.createElement(Button, { + variant: "primary", + icon: "plus" + }, t('kt.add_new')))), /*#__PURE__*/React.createElement("div", { + className: "subtabs" + }, /*#__PURE__*/React.createElement("div", { + className: `subtab ${tab === 'kunden' ? 'active' : ''}`, + onClick: () => { + setTab('kunden'); + setSearch(''); + } + }, /*#__PURE__*/React.createElement(Icon, { + name: "shopping", + size: 16 + }), " Kunden"), /*#__PURE__*/React.createElement("div", { + className: `subtab ${tab === 'lieferanten' ? 'active' : ''}`, + onClick: () => { + setTab('lieferanten'); + setSearch(''); + } + }, /*#__PURE__*/React.createElement(Icon, { + name: "briefcase", + size: 16 + }), " Lieferanten")), /*#__PURE__*/React.createElement(Card, { + style: { + marginBottom: 'var(--space-4)' + } + }, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + gap: 'var(--space-4)', + flexWrap: 'wrap', + alignItems: 'flex-end' + } + }, /*#__PURE__*/React.createElement("div", { + style: { + flex: '1 1 300px' + } + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, t('common.suchen')), /*#__PURE__*/React.createElement("div", { + style: { + position: 'relative' + } + }, /*#__PURE__*/React.createElement(Icon, { + name: "search", + size: 16, + style: { + position: 'absolute', + left: 'var(--space-3)', + top: '50%', + transform: 'translateY(-50%)', + color: 'var(--color-text-muted)' + } + }), /*#__PURE__*/React.createElement("input", { + className: "input", + style: { + paddingLeft: 'var(--space-8)' + }, + placeholder: t('kt.suche'), + value: search, + onChange: e => setSearch(e.target.value) + }))))), filtered.length === 0 ? /*#__PURE__*/React.createElement(Card, null, /*#__PURE__*/React.createElement(EmptyState, { + icon: "contacts", + title: "Keine Kontakte", + text: "Noch keine Kontakte angelegt." + })) : view === 'table' ? /*#__PURE__*/React.createElement(Card, null, /*#__PURE__*/React.createElement("div", { + style: { + overflowX: 'auto' + } + }, /*#__PURE__*/React.createElement("table", { + className: "data-table" + }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", null, "Firma"), /*#__PURE__*/React.createElement("th", null, "Ansprechpartner"), /*#__PURE__*/React.createElement("th", { + className: "hide-mobile" + }, "Land"), /*#__PURE__*/React.createElement("th", { + className: "hide-mobile" + }, "USt-IdNr."), /*#__PURE__*/React.createElement("th", { + className: "hide-mobile" + }, "Status"), /*#__PURE__*/React.createElement("th", null, "Aktion"))), /*#__PURE__*/React.createElement("tbody", null, filtered.map(c => /*#__PURE__*/React.createElement("tr", { + key: c.id + }, /*#__PURE__*/React.createElement("td", { + style: { + fontWeight: 'var(--font-weight-semibold)' + } + }, c.firmenname), /*#__PURE__*/React.createElement("td", null, c.ansprechpartner), /*#__PURE__*/React.createElement("td", { + className: "hide-mobile" + }, c.land), /*#__PURE__*/React.createElement("td", { + className: "hide-mobile", + style: { + fontFamily: 'var(--font-mono)', + fontSize: 'var(--font-size-xs)' + } + }, c.ustId || '-'), /*#__PURE__*/React.createElement("td", { + className: "hide-mobile" + }, ustBadge(c.ustStatus)), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + gap: 'var(--space-1)' + } + }, /*#__PURE__*/React.createElement("button", { + className: "btn btn-ghost btn-sm" + }, /*#__PURE__*/React.createElement(Icon, { + name: "eye", + size: 16 + })), role !== 'buchhaltung' && /*#__PURE__*/React.createElement("button", { + className: "btn btn-ghost btn-sm" + }, /*#__PURE__*/React.createElement(Icon, { + name: "edit", + size: 16 + })))))))))) : /*#__PURE__*/React.createElement("div", { + className: "card-grid" + }, filtered.map(c => /*#__PURE__*/React.createElement("div", { + key: c.id, + className: "contact-card" + }, /*#__PURE__*/React.createElement("div", { + className: "contact-card-header" + }, /*#__PURE__*/React.createElement("div", { + style: { + width: 40, + height: 40, + borderRadius: 'var(--radius-md)', + background: tab === 'kunden' ? 'var(--color-primary-light)' : 'var(--color-info-light)', + color: tab === 'kunden' ? 'var(--color-primary)' : 'var(--color-info)', + display: 'flex', + alignItems: 'center', + justifyContent: 'center', + flexShrink: 0 + } + }, /*#__PURE__*/React.createElement(Icon, { + name: tab === 'kunden' ? 'shopping' : 'briefcase', + size: 20 + })), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + className: "contact-card-name" + }, c.firmenname), /*#__PURE__*/React.createElement("div", { + className: "contact-card-person" + }, c.ansprechpartner))), /*#__PURE__*/React.createElement("div", { + className: "contact-card-info" + }, /*#__PURE__*/React.createElement("div", { + className: "contact-card-info-item" + }, /*#__PURE__*/React.createElement(Icon, { + name: "location", + size: 14 + }), " ", c.land), /*#__PURE__*/React.createElement("div", { + className: "contact-card-info-item" + }, /*#__PURE__*/React.createElement(Icon, { + name: "mail", + size: 14 + }), " ", c.email), /*#__PURE__*/React.createElement("div", { + className: "contact-card-info-item" + }, /*#__PURE__*/React.createElement(Icon, { + name: "phone", + size: 14 + }), " ", c.telefon)))))); +}; + +// ============ VERKAUFSMODUL (v7 list first) ============ +const mockVerkaeufe = [{ + id: 1, + fahrzeug: 'Mercedes Actros 1845 LS', + fin: 'WDB9066351L123456', + kunde: 'Mueller Transport GmbH', + datum: '2026-07-05', + betrag: 45000, + status: 'abgeschlossen', + mwstTyp: 'inland', + steuer: 8550, + gesamt: 53550 +}, { + id: 2, + fahrzeug: 'MAN TGL 12.180', + fin: 'WMAUYYT1XPA123456', + kunde: 'Bauer Bauunternehmen GmbH', + datum: '2026-07-10', + betrag: 29500, + status: 'pruefung', + mwstTyp: 'inland', + steuer: 5605, + gesamt: 35105 +}, { + id: 3, + fahrzeug: 'BMW X5 xDrive30d', + fin: 'WBAJA9C50K8123456', + kunde: 'Van den Berg Logistics B.V.', + datum: '2026-07-08', + betrag: 52000, + status: 'entwurf', + mwstTyp: 'eu_ausland', + steuer: 0, + gesamt: 52000 +}, { + id: 4, + fahrzeug: 'Volvo FH16 750', + fin: 'YV2XK0DG5LA123456', + kunde: 'Spedition Hartmann KG', + datum: '2026-06-28', + betrag: 55000, + status: 'abgeschlossen', + mwstTyp: 'inland', + steuer: 10450, + gesamt: 65450 +}, { + id: 5, + fahrzeug: 'Scania R 500 Highline', + fin: 'SCNR5002019123456', + kunde: 'Mueller Transport GmbH', + datum: '2026-07-12', + betrag: 38000, + status: 'entwurf', + mwstTyp: 'inland', + steuer: 7220, + gesamt: 45220 +}, { + id: 6, + fahrzeug: 'Liebherr R 926', + fin: 'LIR92620201234567', + kunde: 'Bauer Bauunternehmen GmbH', + datum: '2026-06-20', + betrag: 89000, + status: 'storniert', + mwstTyp: 'inland', + steuer: 16910, + gesamt: 105910 +}, { + id: 7, + fahrzeug: 'Toyota 8FBE20', + fin: 'TOY8FBE20220123456', + kunde: 'Schmidt Baumaschinen GmbH', + datum: '2026-07-01', + betrag: 18500, + status: 'abgeschlossen', + mwstTyp: 'inland', + steuer: 3515, + gesamt: 22015 +}]; +const verkaufStatusBadge = s => { + const m = { + entwurf: { + cls: 'verkauf-status-entwurf', + l: 'Entwurf' + }, + pruefung: { + cls: 'verkauf-status-pruefung', + l: 'Pruefung' + }, + abgeschlossen: { + cls: 'verkauf-status-abgeschlossen', + l: 'Abgeschlossen' + }, + storniert: { + cls: 'verkauf-status-storniert', + l: 'Storniert' + } + }; + const c = m[s] || m.entwurf; + return /*#__PURE__*/React.createElement("span", { + className: `verkauf-status-badge ${c.cls}` + }, c.l); +}; +const mwstTypLabel = t => t === 'inland' ? 'Inland' : t === 'eu_ausland' ? 'EU-Ausland' : 'Drittland'; +const VerkaufsModul = ({ + navigate, + role, + preselectVehicle +}) => { + const [viewMode, setViewMode] = useState('list'); + const [view, setView] = useState('table'); + const [search, setSearch] = useState(''); + const [filterStatus, setFilterStatus] = useState('alle'); + const [sortBy, setSortBy] = useState('datum'); + const [sortDir, setSortDir] = useState('desc'); + const [showWizard, setShowWizard] = useState(false); + const [detailId, setDetailId] = useState(null); + const filtered = useMemo(() => { + let r = mockVerkaeufe.filter(v => { + const ms = !search || v.fahrzeug.toLowerCase().includes(search.toLowerCase()) || v.kunde.toLowerCase().includes(search.toLowerCase()) || v.fin.toLowerCase().includes(search.toLowerCase()); + const mst = filterStatus === 'alle' || v.status === filterStatus; + return ms && mst; + }); + r.sort((a, b) => { + const av = a[sortBy], + bv = b[sortBy]; + if (typeof av === 'number') return sortDir === 'asc' ? av - bv : bv - av; + return sortDir === 'asc' ? String(av).localeCompare(String(bv)) : String(bv).localeCompare(String(av)); + }); + return r; + }, [search, filterStatus, sortBy, sortDir]); + const handleSort = col => { + if (sortBy === col) setSortDir(sortDir === 'asc' ? 'desc' : 'asc');else { + setSortBy(col); + setSortDir('asc'); + } + }; + if (showWizard) return /*#__PURE__*/React.createElement(VerkaufWizard, { + navigate: navigate, + role: role, + preselectVehicle: preselectVehicle, + onClose: () => setShowWizard(false) + }); + if (detailId) return /*#__PURE__*/React.createElement(VerkaufDetail, { + verkauf: mockVerkaeufe.find(v => v.id === detailId), + onBack: () => setDetailId(null), + navigate: navigate + }); + return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center', + marginBottom: 'var(--space-6)', + flexWrap: 'wrap', + gap: 'var(--space-4)' + } + }, /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("h1", { + style: { + fontSize: 'var(--font-size-2xl)', + fontWeight: 'var(--font-weight-bold)' + } + }, t('vk.title')), /*#__PURE__*/React.createElement("p", { + style: { + color: 'var(--color-text-secondary)', + fontSize: 'var(--font-size-sm)' + } + }, filtered.length, " Verkaeufe")), /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + gap: 'var(--space-2)', + alignItems: 'center' + } + }, /*#__PURE__*/React.createElement("div", { + className: "view-toggle" + }, /*#__PURE__*/React.createElement("button", { + className: `view-toggle-btn ${viewMode === 'list' ? 'active' : ''}`, + onClick: () => setViewMode('list') + }, /*#__PURE__*/React.createElement(Icon, { + name: "list", + size: 16 + }), " Liste"), /*#__PURE__*/React.createElement("button", { + className: `view-toggle-btn ${viewMode === 'calendar' ? 'active' : ''}`, + onClick: () => setViewMode('calendar') + }, /*#__PURE__*/React.createElement(Icon, { + name: "calendar", + size: 16 + }), " Kalender")), viewMode === 'list' && /*#__PURE__*/React.createElement(ViewToggle, { + view: view, + onChange: setView + }), role !== 'buchhaltung' && /*#__PURE__*/React.createElement(Button, { + variant: "primary", + icon: "plus", + onClick: () => setShowWizard(true) + }, t('vk.neuer_verkauf')))), viewMode === 'calendar' ? /*#__PURE__*/React.createElement(VerkaufKalender, { + navigate: navigate + }) : /*#__PURE__*/React.createElement(React.Fragment, null, /*#__PURE__*/React.createElement(Card, { + style: { + marginBottom: 'var(--space-4)' + } + }, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + gap: 'var(--space-4)', + flexWrap: 'wrap', + alignItems: 'flex-end' + } + }, /*#__PURE__*/React.createElement("div", { + style: { + flex: '1 1 300px' + } + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Suche (Fahrzeug, Kunde, FIN)"), /*#__PURE__*/React.createElement("div", { + style: { + position: 'relative' + } + }, /*#__PURE__*/React.createElement(Icon, { + name: "search", + size: 16, + style: { + position: 'absolute', + left: 'var(--space-3)', + top: '50%', + transform: 'translateY(-50%)', + color: 'var(--color-text-muted)' + } + }), /*#__PURE__*/React.createElement("input", { + className: "input", + style: { + paddingLeft: 'var(--space-8)' + }, + placeholder: "Verkauf suchen...", + value: search, + onChange: e => setSearch(e.target.value) + }))), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Status"), /*#__PURE__*/React.createElement("select", { + className: "select", + value: filterStatus, + onChange: e => setFilterStatus(e.target.value) + }, /*#__PURE__*/React.createElement("option", { + value: "alle" + }, "Alle"), /*#__PURE__*/React.createElement("option", { + value: "entwurf" + }, "Entwurf"), /*#__PURE__*/React.createElement("option", { + value: "pruefung" + }, "Pruefung"), /*#__PURE__*/React.createElement("option", { + value: "abgeschlossen" + }, "Abgeschlossen"), /*#__PURE__*/React.createElement("option", { + value: "storniert" + }, "Storniert"))))), filtered.length === 0 ? /*#__PURE__*/React.createElement(Card, null, /*#__PURE__*/React.createElement(EmptyState, { + icon: "sale", + title: "Keine Verkaeufe", + text: "Noch keine Verkaeufe angelegt.", + action: role !== 'buchhaltung' && /*#__PURE__*/React.createElement(Button, { + variant: "primary", + icon: "plus", + onClick: () => setShowWizard(true) + }, t('vk.neuer_verkauf')) + })) : view === 'table' ? /*#__PURE__*/React.createElement(Card, null, /*#__PURE__*/React.createElement("div", { + style: { + overflowX: 'auto' + } + }, /*#__PURE__*/React.createElement("table", { + className: "data-table" + }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", { + className: sortBy === 'fahrzeug' ? 'sorted' : '', + onClick: () => handleSort('fahrzeug') + }, "Fahrzeug"), /*#__PURE__*/React.createElement("th", null, "Kunde"), /*#__PURE__*/React.createElement("th", { + className: sortBy === 'datum' ? 'sorted' : '', + onClick: () => handleSort('datum') + }, "Datum"), /*#__PURE__*/React.createElement("th", { + className: sortBy === 'betrag' ? 'sorted' : '', + onClick: () => handleSort('betrag') + }, "Betrag"), /*#__PURE__*/React.createElement("th", null, "Status"), /*#__PURE__*/React.createElement("th", null, "MwSt-Typ"))), /*#__PURE__*/React.createElement("tbody", null, filtered.map(v => /*#__PURE__*/React.createElement("tr", { + key: v.id, + onClick: () => setDetailId(v.id), + style: { + cursor: 'pointer' + } + }, /*#__PURE__*/React.createElement("td", { + style: { + fontWeight: 'var(--font-weight-semibold)' + } + }, v.fahrzeug), /*#__PURE__*/React.createElement("td", null, v.kunde), /*#__PURE__*/React.createElement("td", null, formatDate(v.datum)), /*#__PURE__*/React.createElement("td", { + style: { + fontWeight: 'var(--font-weight-semibold)' + } + }, formatPrice(v.betrag)), /*#__PURE__*/React.createElement("td", null, verkaufStatusBadge(v.status)), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "info" + }, mwstTypLabel(v.mwstTyp))))))))) : /*#__PURE__*/React.createElement("div", { + className: "card-grid" + }, filtered.map(v => /*#__PURE__*/React.createElement("div", { + key: v.id, + className: "verkauf-card", + onClick: () => setDetailId(v.id) + }, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'flex-start', + marginBottom: 'var(--space-2)' + } + }, /*#__PURE__*/React.createElement("div", { + style: { + fontWeight: 'var(--font-weight-semibold)', + fontSize: 'var(--font-size-sm)' + } + }, v.fahrzeug), verkaufStatusBadge(v.status)), /*#__PURE__*/React.createElement("div", { + style: { + fontSize: 'var(--font-size-xs)', + color: 'var(--color-text-secondary)', + marginBottom: 'var(--space-2)' + } + }, v.kunde), /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + justifyContent: 'space-between', + alignItems: 'center' + } + }, /*#__PURE__*/React.createElement("div", { + style: { + fontWeight: 'var(--font-weight-bold)', + color: 'var(--color-primary)' + } + }, formatPrice(v.betrag)), /*#__PURE__*/React.createElement("div", { + style: { + fontSize: 'var(--font-size-xs)', + color: 'var(--color-text-muted)' + } + }, formatDate(v.datum), " · ", mwstTypLabel(v.mwstTyp)))))))); +}; +const VerkaufDetail = ({ + verkauf, + onBack, + navigate +}) => { + const [activeTab, setActiveTab] = useState('uebersicht'); + if (!verkauf) return null; + const tabs = [{ + id: 'uebersicht', + label: 'Uebersicht' + }, { + id: 'dokumente', + label: 'Dokumente' + }, { + id: 'zahlung', + label: 'Zahlungsverlauf' + }, { + id: 'termine', + label: 'Termine' + }]; + return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + alignItems: 'center', + gap: 'var(--space-4)', + marginBottom: 'var(--space-6)' + } + }, /*#__PURE__*/React.createElement(Button, { + variant: "ghost", + icon: "chevronLeft", + onClick: onBack + }, "Zurueck"), /*#__PURE__*/React.createElement("div", { + style: { + flex: 1 + } + }, /*#__PURE__*/React.createElement("h1", { + style: { + fontSize: 'var(--font-size-2xl)', + fontWeight: 'var(--font-weight-bold)' + } + }, verkauf.fahrzeug), /*#__PURE__*/React.createElement("p", { + style: { + color: 'var(--color-text-secondary)', + fontSize: 'var(--font-size-sm)' + } + }, "FIN: ", verkauf.fin, " · ", formatDate(verkauf.datum))), verkaufStatusBadge(verkauf.status)), /*#__PURE__*/React.createElement("div", { + className: "tabs" + }, tabs.map(tab => /*#__PURE__*/React.createElement("div", { + key: tab.id, + className: `tab ${activeTab === tab.id ? 'active' : ''}`, + onClick: () => setActiveTab(tab.id) + }, tab.label))), activeTab === 'uebersicht' && /*#__PURE__*/React.createElement(Card, { + title: "Verkaufsuebersicht" + }, /*#__PURE__*/React.createElement("div", { + className: "info-grid" + }, /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Fahrzeug"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, verkauf.fahrzeug)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "FIN"), /*#__PURE__*/React.createElement("div", { + className: "info-value", + style: { + fontFamily: 'var(--font-mono)' + } + }, verkauf.fin)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Kunde"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, verkauf.kunde)), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Datum"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, formatDate(verkauf.datum))), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Netto-Betrag"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, formatPrice(verkauf.betrag))), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "MwSt-Typ"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, /*#__PURE__*/React.createElement(Badge, { + variant: "info" + }, mwstTypLabel(verkauf.mwstTyp)))), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Steuerbetrag"), /*#__PURE__*/React.createElement("div", { + className: "info-value" + }, formatPrice(verkauf.steuer))), /*#__PURE__*/React.createElement("div", { + className: "info-item" + }, /*#__PURE__*/React.createElement("div", { + className: "info-label" + }, "Gesamt (brutto)"), /*#__PURE__*/React.createElement("div", { + className: "info-value", + style: { + fontSize: 'var(--font-size-lg)', + color: 'var(--color-primary)' + } + }, formatPrice(verkauf.gesamt))))), activeTab === 'dokumente' && /*#__PURE__*/React.createElement(Card, { + title: "Dokumente" + }, /*#__PURE__*/React.createElement("table", { + className: "data-table" + }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", null, "Dokument"), /*#__PURE__*/React.createElement("th", null, "Typ"), /*#__PURE__*/React.createElement("th", null, "Aktion"))), /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "Kaufvertrag.pdf"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "primary" + }, "Vertrag")), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("button", { + className: "btn btn-ghost btn-sm" + }, /*#__PURE__*/React.createElement(Icon, { + name: "download", + size: 16 + })))), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "Rechnung.pdf"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "info" + }, "Rechnung")), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("button", { + className: "btn btn-ghost btn-sm" + }, /*#__PURE__*/React.createElement(Icon, { + name: "download", + size: 16 + })))), verkauf.mwstTyp === 'eu_ausland' && /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "Lieferbescheinigung.pdf"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "warning" + }, "Zertifikat")), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement("button", { + className: "btn btn-ghost btn-sm" + }, /*#__PURE__*/React.createElement(Icon, { + name: "download", + size: 16 + }))))))), activeTab === 'zahlung' && /*#__PURE__*/React.createElement(Card, { + title: "Zahlungsverlauf" + }, /*#__PURE__*/React.createElement("table", { + className: "data-table" + }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", null, "Datum"), /*#__PURE__*/React.createElement("th", null, "Betrag"), /*#__PURE__*/React.createElement("th", null, "Methode"), /*#__PURE__*/React.createElement("th", null, "Status"))), /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, formatDate(verkauf.datum)), /*#__PURE__*/React.createElement("td", null, formatPrice(verkauf.gesamt)), /*#__PURE__*/React.createElement("td", null, "Ueberweisung"), /*#__PURE__*/React.createElement("td", null, verkauf.status === 'abgeschlossen' ? /*#__PURE__*/React.createElement(Badge, { + variant: "success" + }, "Bezahlt") : /*#__PURE__*/React.createElement(Badge, { + variant: "warning" + }, "Offen")))))), activeTab === 'termine' && /*#__PURE__*/React.createElement(Card, { + title: "Termine" + }, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + flexDirection: 'column', + gap: 'var(--space-3)' + } + }, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + alignItems: 'center', + gap: 'var(--space-3)', + padding: 'var(--space-3)', + border: '1px solid var(--color-border)', + borderRadius: 'var(--radius-md)' + } + }, /*#__PURE__*/React.createElement(Icon, { + name: "calendar", + size: 20, + style: { + color: 'var(--color-info)' + } + }), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + style: { + fontWeight: 'var(--font-weight-medium)' + } + }, "Ueberfuehrung"), /*#__PURE__*/React.createElement("div", { + style: { + fontSize: 'var(--font-size-xs)', + color: 'var(--color-text-muted)' + } + }, "Geplant: ", formatDate(verkauf.datum))), /*#__PURE__*/React.createElement(Badge, { + variant: "info" + }, "Geplant")), /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + alignItems: 'center', + gap: 'var(--space-3)', + padding: 'var(--space-3)', + border: '1px solid var(--color-border)', + borderRadius: 'var(--radius-md)' + } + }, /*#__PURE__*/React.createElement(Icon, { + name: "package", + size: 20, + style: { + color: 'var(--color-warning)' + } + }), /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + style: { + fontWeight: 'var(--font-weight-medium)' + } + }, "Lieferung"), /*#__PURE__*/React.createElement("div", { + style: { + fontSize: 'var(--font-size-xs)', + color: 'var(--color-text-muted)' + } + }, "Geplant: ", formatDate(verkauf.datum))), /*#__PURE__*/React.createElement(Badge, { + variant: "warning" + }, "Geplant"))))); +}; + +// ============ KI COPILOT (v7 ChatGPT-like) ============ +const KiCopilot = ({ + navigate, + role +}) => { + const [messages, setMessages] = useState([{ + type: 'ai', + text: 'Hallo Max! Ich bin Ihr KI-Assistent. Ich kann Fahrzeuge anlegen, suchen, verkaufen und Dokumente erstellen. Was kann ich fuer Sie tun?' + }]); + const [input, setInput] = useState(''); + const [loading, setLoading] = useState(false); + const [listening, setListening] = useState(false); + const [speechSupported, setSpeechSupported] = useState(true); + const textareaRef = useRef(null); + const messagesEnd = useRef(null); + const recognitionRef = useRef(null); + useEffect(() => { + messagesEnd.current?.scrollIntoView({ + behavior: 'smooth' + }); + }, [messages]); + useEffect(() => { + document.body.classList.add('copilot-active'); + return () => document.body.classList.remove('copilot-active'); + }, []); + useEffect(() => { + const SR = window.SpeechRecognition || window.webkitSpeechRecognition; + if (!SR) { + setSpeechSupported(false); + return; + } + const rec = new SR(); + rec.lang = 'de-DE'; + rec.continuous = false; + rec.interimResults = true; + rec.onresult = e => { + let text = ''; + for (let i = 0; i < e.results.length; i++) text += e.results[i][0].transcript; + setInput(text); + autoGrow(); + }; + rec.onerror = e => { + setListening(false); + }; + rec.onend = () => { + setListening(false); + }; + recognitionRef.current = rec; + }, []); + const autoGrow = () => { + const ta = textareaRef.current; + if (ta) { + ta.style.height = '48px'; + ta.style.height = Math.min(ta.scrollHeight, 200) + 'px'; + } + }; + const toggleMic = () => { + if (!speechSupported || !recognitionRef.current) return; + if (listening) { + recognitionRef.current.stop(); + setListening(false); + } else { + try { + recognitionRef.current.start(); + setListening(true); + } catch (e) {} + } + }; + const sendMessage = text => { + const msg = text || input; + if (!msg.trim() || loading) return; + setMessages(prev => [...prev, { + type: 'user', + text: msg + }]); + setInput(''); + if (textareaRef.current) textareaRef.current.style.height = '48px'; + setLoading(true); + setTimeout(() => { + let r = 'Ich verstehe Ihren Befehl. Bitte spezifizieren Sie genauer.'; + const ml = msg.toLowerCase(); + if (ml.includes('lege') && ml.includes('fahrzeug')) r = 'Ich habe die Daten extrahiert und das Fahrzeugformular vorausgefuellt. Bitte ueberpruefen Sie die Daten und bestaetigen Sie zum Speichern. Das Formular ist jetzt geoeffnet.';else if (ml.includes('finde') || ml.includes('suche')) r = 'Ich habe 3 Fahrzeuge gefunden, die Ihren Kriterien entsprechen. Die Ergebnisse werden in der Bestandsliste angezeigt.';else if (ml.includes('verkaufe') || ml.includes('kaufvertrag')) r = 'Verkaufsprozess gestartet. Ich habe Kaeufer und Fahrzeug identifiziert. Der Verkaufs-Assistent ist jetzt geoeffnet.';else if (ml.includes('rechnung')) r = 'Rechnung RE-2026-047 wurde aus dem letzten Verkauf generiert. Die PDF steht zum Download bereit.';else if (ml.includes('kontakt') || ml.includes('kunde')) r = 'Ich habe die Kontaktverwaltung geoeffnet. Sie koennen zwischen Kunden und Lieferanten wechseln.';else if (ml.includes('preis') || ml.includes('vergleich')) r = 'Ich vergleiche Preise aehnlicher Fahrzeuge auf mobile.de. Bitte waehlen Sie ein Fahrzeug aus der Bestandsliste.'; + setMessages(prev => [...prev, { + type: 'ai', + text: r + }]); + setLoading(false); + }, 1500); + }; + const handleKeyDown = e => { + if (e.key === 'Enter' && !e.shiftKey) { + e.preventDefault(); + sendMessage(); + } + }; + const chips = ['Fahrzeug suchen', 'Neuer Verkauf', 'Kontakte', 'Preisvergleich', 'Dokument erstellen', 'Letzte Verkaeufe']; + return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + style: { + marginBottom: 'var(--space-4)' + } + }, /*#__PURE__*/React.createElement("h1", { + style: { + fontSize: 'var(--font-size-2xl)', + fontWeight: 'var(--font-weight-bold)' + } + }, t('ki.title')), /*#__PURE__*/React.createElement("p", { + style: { + color: 'var(--color-text-secondary)', + fontSize: 'var(--font-size-sm)', + marginTop: 'var(--space-1)' + } + }, "KI-Assistent via OpenRouter - Text & Spracheingabe")), /*#__PURE__*/React.createElement("div", { + className: "copilot-container" + }, /*#__PURE__*/React.createElement("div", { + className: "copilot-chat" + }, messages.map((msg, i) => /*#__PURE__*/React.createElement("div", { + key: i, + className: msg.type === 'user' ? 'chat-msg-user' : 'chat-msg-ai' + }, msg.type === 'ai' && /*#__PURE__*/React.createElement("div", { + className: "chat-ai-avatar" + }, /*#__PURE__*/React.createElement(Icon, { + name: "ai", + size: 20 + })), /*#__PURE__*/React.createElement("div", { + className: "chat-bubble-full" + }, msg.text))), loading && /*#__PURE__*/React.createElement("div", { + className: "chat-msg-ai" + }, /*#__PURE__*/React.createElement("div", { + className: "chat-ai-avatar" + }, /*#__PURE__*/React.createElement(Icon, { + name: "ai", + size: 20 + })), /*#__PURE__*/React.createElement("div", { + className: "chat-bubble-full" + }, /*#__PURE__*/React.createElement("div", { + className: "typing-indicator" + }, /*#__PURE__*/React.createElement("div", { + className: "typing-dot" + }), /*#__PURE__*/React.createElement("div", { + className: "typing-dot" + }), /*#__PURE__*/React.createElement("div", { + className: "typing-dot" + })))), /*#__PURE__*/React.createElement("div", { + ref: messagesEnd + })), /*#__PURE__*/React.createElement("div", { + className: "copilot-input-container" + }, /*#__PURE__*/React.createElement("div", { + className: "copilot-chips" + }, chips.map((chip, i) => /*#__PURE__*/React.createElement("div", { + key: i, + className: "chat-chip", + onClick: () => sendMessage(chip) + }, chip))), /*#__PURE__*/React.createElement("div", { + className: "copilot-input-row" + }, /*#__PURE__*/React.createElement("button", { + className: `chat-mic-btn ${listening ? 'recording' : ''}`, + onClick: toggleMic, + title: speechSupported ? 'Spracheingabe' : 'Spracheingabe nicht unterstuetzt', + disabled: !speechSupported + }, /*#__PURE__*/React.createElement(Icon, { + name: "mic", + size: 20 + })), /*#__PURE__*/React.createElement("textarea", { + ref: textareaRef, + className: "copilot-textarea", + placeholder: t('ki.placeholder'), + value: input, + onChange: e => { + setInput(e.target.value); + autoGrow(); + }, + onKeyDown: handleKeyDown, + rows: 1 + }), /*#__PURE__*/React.createElement("button", { + className: "chat-send-btn", + onClick: () => sendMessage(), + disabled: !input.trim() || loading, + title: "Senden" + }, /*#__PURE__*/React.createElement(Icon, { + name: "send", + size: 20 + })))), !speechSupported && /*#__PURE__*/React.createElement("div", { + style: { + textAlign: 'center', + fontSize: 'var(--font-size-xs)', + color: 'var(--color-text-muted)', + padding: 'var(--space-2)' + } + }, "Spracheingabe nicht unterstuetzt - bitte Text eingeben"), " ")); +}; + +// ============ EINSTELLUNGEN ============ +const Einstellungen = ({ + navigate +}) => { + const [activeTab, setActiveTab] = useState('stammdaten'); + const [stammdatenSub, setStammdatenSub] = useState('steuer'); + const tabs = [{ + id: 'stammdaten', + label: 'Stammdaten' + }, { + id: 'vorlagen', + label: 'Vertragsvorlagen' + }, { + id: 'benutzer', + label: 'Benutzerverwaltung' + }, { + id: 'firma', + label: 'Firmenprofil' + }]; + const stammdatenSubs = [{ + id: 'steuer', + label: 'Steuer & MwSt', + icon: 'percentage' + }, { + id: 'waehrungen', + label: 'Waehrungen', + icon: 'currency' + }, { + id: 'lieferbedingungen', + label: 'Incoterms', + icon: 'truck' + }, { + id: 'zahlungsbedingungen', + label: 'Zahlungsbedingungen', + icon: 'euro' + }, { + id: 'versicherungen', + label: 'Versicherungen', + icon: 'shield' + }, { + id: 'gewaehrleistung', + label: 'Gewaehrleistung', + icon: 'certificate' + }, { + id: 'lkw_typen', + label: 'LKW-Typen', + icon: 'truck_type' + }, { + id: 'baumaschinen_typen', + label: 'Baumaschinen', + icon: 'wrench' + }, { + id: 'fahrzeugzustaende', + label: 'Zustaende', + icon: 'tag' + }, { + id: 'kraftstoffarten', + label: 'Kraftstoffe', + icon: 'gas' + }, { + id: 'abgasnormen', + label: 'Abgasnormen', + icon: 'layers' + }, { + id: 'bereifung', + label: 'Bereifung', + icon: 'road' + }, { + id: 'zulassungsstatus', + label: 'Zulassung', + icon: 'certificate' + }]; + return /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + style: { + marginBottom: 'var(--space-6)' + } + }, /*#__PURE__*/React.createElement("h1", { + style: { + fontSize: 'var(--font-size-2xl)', + fontWeight: 'var(--font-weight-bold)' + } + }, t('set.title'))), /*#__PURE__*/React.createElement("div", { + className: "tabs" + }, tabs.map(tab => /*#__PURE__*/React.createElement("div", { + key: tab.id, + className: `tab ${activeTab === tab.id ? 'active' : ''}`, + onClick: () => setActiveTab(tab.id) + }, tab.label))), activeTab === 'stammdaten' && /*#__PURE__*/React.createElement("div", null, /*#__PURE__*/React.createElement("div", { + className: "subtabs" + }, stammdatenSubs.map(s => /*#__PURE__*/React.createElement("div", { + key: s.id, + className: `subtab ${stammdatenSub === s.id ? 'active' : ''}`, + onClick: () => setStammdatenSub(s.id) + }, /*#__PURE__*/React.createElement(Icon, { + name: s.icon, + size: 14 + }), " ", s.label))), stammdatenSub === 'steuer' && /*#__PURE__*/React.createElement(Card, { + title: "Steuerklassen" + }, /*#__PURE__*/React.createElement("table", { + className: "stammdaten-table" + }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", null, "Bezeichnung"), /*#__PURE__*/React.createElement("th", null, "Satz"), /*#__PURE__*/React.createElement("th", null, "Status"))), /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "EU-Inland"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "primary" + }, "19%")), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "success" + }, "Aktiv"))), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "EU-Ausland"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "warning" + }, "0%")), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "success" + }, "Aktiv"))), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "Drittland"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "warning" + }, "0%")), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "success" + }, "Aktiv")))))), stammdatenSub === 'waehrungen' && /*#__PURE__*/React.createElement(Card, { + title: "Waehrungen" + }, /*#__PURE__*/React.createElement("table", { + className: "stammdaten-table" + }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", null, "Waehrung"), /*#__PURE__*/React.createElement("th", null, "Code"), /*#__PURE__*/React.createElement("th", null, "Kurs"))), /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "Euro"), /*#__PURE__*/React.createElement("td", null, "EUR"), /*#__PURE__*/React.createElement("td", null, "1.0000")), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "USD"), /*#__PURE__*/React.createElement("td", null, "USD"), /*#__PURE__*/React.createElement("td", null, "0.9234")), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "CHF"), /*#__PURE__*/React.createElement("td", null, "CHF"), /*#__PURE__*/React.createElement("td", null, "1.0523"))))), stammdatenSub === 'lieferbedingungen' && /*#__PURE__*/React.createElement(Card, { + title: "Incoterms" + }, /*#__PURE__*/React.createElement("div", { + style: { + display: 'flex', + flexWrap: 'wrap', + gap: 'var(--space-2)' + } + }, ['EXW', 'FOB', 'CIF', 'DAP', 'DDP', 'FCA'].map(c => /*#__PURE__*/React.createElement(Badge, { + key: c, + variant: "primary" + }, c)))), stammdatenSub === 'zahlungsbedingungen' && /*#__PURE__*/React.createElement(Card, { + title: "Zahlungsbedingungen" + }, /*#__PURE__*/React.createElement("table", { + className: "stammdaten-table" + }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", null, "Bezeichnung"), /*#__PURE__*/React.createElement("th", null, "Frist"))), /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "Vorkasse"), /*#__PURE__*/React.createElement("td", null, "Sofort")), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "30 Tage netto"), /*#__PURE__*/React.createElement("td", null, "30T")), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "Ratenzahlung"), /*#__PURE__*/React.createElement("td", null, "3 Raten"))))), (stammdatenSub === 'versicherungen' || stammdatenSub === 'gewaehrleistung' || stammdatenSub === 'lkw_typen' || stammdatenSub === 'baumaschinen_typen' || stammdatenSub === 'fahrzeugzustaende' || stammdatenSub === 'kraftstoffarten' || stammdatenSub === 'abgasnormen' || stammdatenSub === 'bereifung' || stammdatenSub === 'zulassungsstatus') && /*#__PURE__*/React.createElement(Card, { + title: stammdatenSubs.find(s => s.id === stammdatenSub)?.label + }, /*#__PURE__*/React.createElement("p", { + style: { + color: 'var(--color-text-secondary)', + fontSize: 'var(--font-size-sm)' + } + }, "Stammdaten verwaltet unter: ", stammdatenSubs.find(s => s.id === stammdatenSub)?.label))), activeTab === 'vorlagen' && /*#__PURE__*/React.createElement(Card, { + title: "Vertragsvorlagen" + }, /*#__PURE__*/React.createElement("table", { + className: "data-table" + }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", null, "Vorlage"), /*#__PURE__*/React.createElement("th", null, "Typ"), /*#__PURE__*/React.createElement("th", null, "Status"))), /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "Kaufvertrag Inland"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "primary" + }, "Inland")), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "success" + }, "Aktiv"))), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "Kaufvertrag EU-Ausland"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "info" + }, "EU")), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "success" + }, "Aktiv"))), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "Rechnung"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "neutral" + }, "Rechnung")), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "success" + }, "Aktiv")))))), activeTab === 'benutzer' && /*#__PURE__*/React.createElement(Card, { + title: "Benutzerverwaltung" + }, /*#__PURE__*/React.createElement("table", { + className: "data-table" + }, /*#__PURE__*/React.createElement("thead", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("th", null, "Name"), /*#__PURE__*/React.createElement("th", null, "Rolle"), /*#__PURE__*/React.createElement("th", null, "Status"))), /*#__PURE__*/React.createElement("tbody", null, /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "Max Mustermann"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "primary" + }, "Admin")), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "success" + }, "Aktiv"))), /*#__PURE__*/React.createElement("tr", null, /*#__PURE__*/React.createElement("td", null, "Sarah Klein"), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "info" + }, "Verkaeufer")), /*#__PURE__*/React.createElement("td", null, /*#__PURE__*/React.createElement(Badge, { + variant: "success" + }, "Aktiv")))))), activeTab === 'firma' && /*#__PURE__*/React.createElement(Card, { + title: "Firmenprofil" + }, /*#__PURE__*/React.createElement("div", { + className: "two-col" + }, /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "Firmenname"), /*#__PURE__*/React.createElement("input", { + className: "input", + defaultValue: "Nutzfahrzeug Handel GmbH" + })), /*#__PURE__*/React.createElement("div", { + className: "form-group" + }, /*#__PURE__*/React.createElement("label", { + className: "label" + }, "USt-IdNr."), /*#__PURE__*/React.createElement("input", { + className: "input", + defaultValue: "DE123456789", + style: { + fontFamily: 'var(--font-mono)' + } + }))), /*#__PURE__*/React.createElement(Button, { + variant: "primary", + icon: "check", + style: { + marginTop: 'var(--space-4)' + } + }, "Speichern"))); +}; + +// ============ MAIN APP ============ +const App = () => { + const { + route, + navigate + } = useRouter(); + const [role, setRole] = useState(localStorage.getItem('erp-role') || 'admin'); + const [toasts, setToasts] = useState([]); + const removeToast = id => setToasts(prev => prev.filter(t => t.id !== id)); + const routeParts = route.split('/').filter(Boolean); + const view = routeParts[0] || 'dashboard'; + const param = routeParts[1]; + const queryStr = route.split('?')[1]; + const query = {}; + if (queryStr) { + queryStr.split('&').forEach(p => { + const [k, v] = p.split('='); + query[k] = v; + }); + } + let content; + switch (view) { + case 'dashboard': + content = /*#__PURE__*/React.createElement(DashboardView, { + navigate: navigate, + role: role + }); + break; + case 'fahrzeuge': + if (param === 'neu') content = /*#__PURE__*/React.createElement(FahrzeugForm, { + navigate: navigate, + editId: query.id + });else content = /*#__PURE__*/React.createElement(FahrzeugListe, { + navigate: navigate, + role: role + }); + break; + case 'fahrzeug': + content = /*#__PURE__*/React.createElement(FahrzeugDetail, { + id: param, + navigate: navigate, + role: role + }); + break; + case 'kontakte': + content = /*#__PURE__*/React.createElement(KontakteListe, { + navigate: navigate, + role: role + }); + break; + case 'verkauf': + content = /*#__PURE__*/React.createElement(VerkaufsModul, { + navigate: navigate, + role: role, + preselectVehicle: query.vehicle + }); + break; + case 'ki-copilot': + content = /*#__PURE__*/React.createElement(KiCopilot, { + navigate: navigate, + role: role + }); + break; + case 'einstellungen': + content = /*#__PURE__*/React.createElement(Einstellungen, { + navigate: navigate + }); + break; + default: + content = /*#__PURE__*/React.createElement(DashboardView, { + navigate: navigate, + role: role + }); + } + return /*#__PURE__*/React.createElement("div", { + className: "app-layout" + }, /*#__PURE__*/React.createElement(Sidebar, { + route: '/' + view, + navigate: navigate, + role: role + }), /*#__PURE__*/React.createElement("div", { + className: "main-content" + }, /*#__PURE__*/React.createElement(Topbar, { + route: route, + role: role, + setRole: setRole, + navigate: navigate + }), /*#__PURE__*/React.createElement("main", { + id: "main-content", + className: "content-area" + }, content))); +}; +ReactDOM.createRoot(document.getElementById('root')).render(/*#__PURE__*/React.createElement(App, null)); diff --git a/ui-prototyp/index.html b/ui-prototyp/index.html new file mode 100644 index 0000000..ce08cc4 --- /dev/null +++ b/ui-prototyp/index.html @@ -0,0 +1,19 @@ + + + + + + ERP Nutzfahrzeuge - Prototyp + + + + + + + + + +
+ + + diff --git a/ui-prototyp/interactions.js b/ui-prototyp/interactions.js new file mode 100644 index 0000000..afc7f68 --- /dev/null +++ b/ui-prototyp/interactions.js @@ -0,0 +1,563 @@ +/* ============================================ + ERP Nutzfahrzeuge - Shared Interactions + ============================================ */ + +// i18n Translations +const translations = { + de: { + // Navigation + 'nav.dashboard': 'Dashboard', + 'nav.fahrzeuge': 'Fahrzeugbestand', + 'nav.fahrzeuge.liste': 'Bestandsliste', + 'nav.fahrzeuge.neu': 'Neues Fahrzeug', + 'nav.kontakte': 'Kontakte', + 'nav.verkauf': 'Verkauf', + 'nav.dateien': 'Dateien', + 'nav.ki-copilot': 'KI-Copilot', + 'nav.einstellungen': 'Einstellungen', + 'nav.benutzerverwaltung': 'Benutzerverwaltung', + 'nav.datev': 'DATEV-Export', + 'nav.rechnungen': 'Rechnungen', + 'nav.main': 'Hauptmenü', + 'nav.verwaltung': 'Verwaltung', + 'nav.ki': 'Künstliche Intelligenz', + // Topbar + 'topbar.search': 'Fahrzeuge, Kontakte, FIN suchen...', + 'topbar.profile': 'Profil', + 'topbar.logout': 'Abmelden', + 'topbar.role': 'Rolle', + // Dashboard + 'dash.title': 'Dashboard', + 'dash.fahrzeuge_im_bestand': 'Fahrzeuge im Bestand', + 'dash.verkaufe_diesen_monat': 'Verkäufe diesen Monat', + 'dash.offene_tasks': 'Offene Tasks', + 'dash.mobilede_sync': 'mobile.de Sync-Status', + 'dash.schnellzugriffe': 'Schnellzugriffe', + 'dash.neues_fahrzeug': 'Neues Fahrzeug anlegen', + 'dash.neuer_verkauf': 'Neuer Verkauf', + 'dash.ki_copilot': 'KI-Copilot öffnen', + 'dash.letzte_aktivitaeten': 'Letzte Aktivitäten', + 'dash.bevorstehende_tasks': 'Bevorstehende Tasks', + 'dash.verkaeufe_entwicklung': 'Verkäufe Entwicklung', + 'dash.top_fahrzeuge': 'Fahrzeuge mit meisten Anfragen', + 'dash.weiter': 'Weiter', + // Fahrzeugbestand + 'fb.title': 'Fahrzeugbestand', + 'fb.suche': 'Fahrzeug suchen (Marke, Modell, FIN)...', + 'fb.filter': 'Filter', + 'fb.alle': 'Alle', + 'fb.lkw': 'LKW', + 'fb.baumaschine': 'Baumaschine', + 'fb.transporter': 'Transporter', + 'fb.add_new': 'Fahrzeug hinzufügen', + 'fb.marke': 'Marke', + 'fb.modell': 'Modell', + 'fb.fin': 'FIN', + 'fb.baujahr': 'Baujahr', + 'fb.km_stand': 'KM-Stand', + 'fb.betriebsstunden': 'Betriebsstunden', + 'fb.preis': 'Preis', + 'fb.status': 'Status', + 'fb.mobilede': 'mobile.de', + 'fb.typ': 'Typ', + 'fb.standort': 'Standort', + 'fb.verfuegbarkeit': 'Verfügbarkeit', + 'fb.verfuegbar': 'Verfügbar', + 'fb.reserviert': 'Reserviert', + 'fb.verkauft': 'Verkauft', + 'fb.gelistet': 'Gelistet', + 'fb.nicht_gelistet': 'Nicht gelistet', + 'fb.fehler': 'Fehler', + 'fb.aktion': 'Aktion', + 'fb.bearbeiten': 'Bearbeiten', + 'fb.details': 'Details', + 'fb.anzeigen': 'Anzeigen', + 'fb.keine_fahrzeuge': 'Keine Fahrzeuge gefunden', + 'fb.keine_fahrzeuge_text': 'Es sind noch keine Fahrzeuge im Bestand. Legen Sie Ihr erstes Fahrzeug an.', + 'fb.fahrzeug_hinzufuegen': 'Fahrzeug hinzufügen', + 'fb.export': 'Export (CSV)', + 'fb.filter_zuruecksetzen': 'Filter zurücksetzen', + // Fahrzeug Detail + 'fd.titel': 'Fahrzeugdetails', + 'fd.allgemein': 'Allgemein', + 'fd.technische_daten': 'Technische Daten', + 'fd.baumaschinen_daten': 'Baumaschinen-Daten', + 'fd.verkaufsinfo': 'Verkaufsinfo', + 'fd.dokumente': 'Dokumente', + 'fd.fotos': 'Fotos', + 'fd.mobilede_status': 'mobile.de Status', + 'fd.bearbeiten': 'Bearbeiten', + 'fd.verkaufen': 'Verkaufen', + 'fd.zurueck': 'Zurück zur Liste', + 'fd.hauptfoto': 'Hauptfoto', + 'fd.keine_fotos': 'Keine Fotos vorhanden', + 'fd.foto_hochladen': 'Foto hochladen', + 'fd.dokument_hochladen': 'Dokument hochladen', + 'fd.kategorie': 'Kategorie', + 'fd.dateiname': 'Dateiname', + 'fd.groesse': 'Größe', + 'fd.upload_datum': 'Upload-Datum', + 'fd.sync_mobilede': 'Auf mobile.de synchronisieren', + 'fd.delisting': 'mobile.de Listing entfernen', + 'fd.bildretusche': 'KI-Bildretusche', + 'fd.preisvergleich': 'Preisvergleich mobile.de', + // Fahrzeug Formular + 'ff.titel_neu': 'Neues Fahrzeug anlegen', + 'ff.titel_bearbeiten': 'Fahrzeug bearbeiten', + 'ff.speichern': 'Speichern', + 'ff.abbrechen': 'Abbrechen', + 'ff.pflichtfeld': 'Pflichtfeld', + 'ff.ocr_upload': 'OCR-Upload (ZB I / ZB II)', + 'ff.ocr_text': 'Fahrzeugschein oder Fahrzeugbrief fotografieren und Daten automatisch ausfüllen', + 'ff.ocr_ausloesen': 'OCR starten', + 'ff.standard_daten': 'Standarddaten', + 'ff.baumaschinen_daten': 'Baumaschinen-spezifische Daten', + 'ff.fahrzeugtyp': 'Fahrzeugtyp', + 'ff.fin_hinweis': '17 Zeichen, eindeutige Fahrzeugidentifikationsnummer', + 'ff.fin_ungueltig': 'FIN muss genau 17 Zeichen haben', + 'ff.fin_doppelt': 'FIN bereits vorhanden', + 'ff.leistung': 'Leistung (kW)', + 'ff.leistung_ps': 'Leistung (PS)', + 'ff.kraftstoffart': 'Kraftstoffart', + 'ff.getriebe': 'Getriebe', + 'ff.farbe': 'Farbe', + 'ff.zustand': 'Zustand', + 'ff.erstzulassung': 'Erstzulassung', + 'ff.neu': 'Neu', + 'ff.gebraucht': 'Gebraucht', + 'ff.lkw_typ': 'LKW-Typ', + 'ff.art': 'Art (Bagger, Radlader, etc.)', + 'ff.aufbau': 'Aufbau', + 'ff.betriebsstunden_wert': 'Betriebsstunden', + 'ff.betriebsstunden_einheit': 'Einheit', + 'ff.stunden': 'Stunden (h)', + 'ff.minuten': 'Minuten (min)', + 'ff.manuell': 'Manuell', + 'ff.automatik': 'Automatik', + 'ff.diesel': 'Diesel', + 'ff.benzin': 'Benzin', + 'ff.elektro': 'Elektro', + 'ff.hybrid': 'Hybrid', + // Kontakte + 'kt.title': 'Kontakt- & Kundenverwaltung', + 'kt.suche': 'Kontakte suchen (Name, Firma, Land)...', + 'kt.add_new': 'Neuer Kontakt', + 'kt.firmenname': 'Firmenname', + 'kt.ansprechpartner': 'Ansprechpartner', + 'kt.land': 'Land', + 'kt.rolle': 'Rolle', + 'kt.ust_id': 'USt-IdNr.', + 'kt.ust_status': 'USt-Status', + 'kt.geprueft': 'Geprüft', + 'kt.ungeprueft': 'Ungeprüft', + 'kt.manuell_best': 'Manuell bestätigt', + 'kt.kaeufer': 'Käufer', + 'kt.verkaeufer': 'Verkäufer', + 'kt.beides': 'Käufer & Verkäufer', + 'kt.detail': 'Detail', + 'kt.keine_kontakte': 'Keine Kontakte gefunden', + 'kt.keine_kontakte_text': 'Es sind noch keine Kontakte angelegt.', + 'kt.neuer_kontakt': 'Neuen Kontakt anlegen', + // Verkauf + 'vk.title': 'Verkaufsmodul', + 'vk.neuer_verkauf': 'Neuer Verkauf', + 'vk.fahrzeug': 'Fahrzeug', + 'vk.kaeufer': 'Käufer', + 'vk.verkaeufer': 'Verkäufer', + 'vk.preis': 'Preis', + 'vk.zahlungsart': 'Zahlungsart', + 'vk.uebergabedatum': 'Übergabedatum', + 'vk.vertragsart': 'Vertragsart', + 'vk.inland': 'EU-Inland', + 'vk.eu_ausland': 'EU-Ausland', + 'vk.drittland': 'Drittland', + 'vk.kaufvertrag': 'Kaufvertrag erstellen', + 'vk.rechnung': 'Rechnung erstellen', + 'vk.lieferbescheinigung': 'Lieferbescheinigung', + 'vk.ust_pruefung': 'USt-IdNr.-Prüfung', + 'vk.gwG_warnung': 'GwG-Warnung: Barzahlung über 10.000 €', + 'vk.gwG_meldung': 'Meldepflicht nach GwG (§ 11 GwG) - Barzahlung überschreitet 10.000 €', + 'vk.identifikation': 'Identifikation des Vertragspartners', + 'vk.ausweis_typ': 'Ausweistyp', + 'vk.ausweis_nr': 'Ausweisnummer', + 'vk.ausstellungsland': 'Ausstellungsland', + 'vk.datum': 'Datum', + 'vk.barzahlung': 'Barzahlung', + 'vk.ueberweisung': 'Überweisung', + 'vk.speichern': 'Verkauf speichern', + 'vk.pdf_generieren': 'PDF generieren', + // KI Copilot + 'ki.title': 'KI-Copilot', + 'ki.placeholder': 'Fragen Sie den KI-Assistenten... (z.B. "Lege neues Fahrzeug an: MAN TGL 2018, 120000 km, 32000 €")', + 'ki.senden': 'Senden', + 'ki.spracheingabe': 'Spracheingabe', + 'ki.historie': 'Verlauf', + 'ki.beispiele': 'Beispiel-Befehle', + 'ki.beispiel1': 'Lege neues Fahrzeug an: Mercedes Actros 2019, 150000 km, 45000 €', + 'ki.beispiel2': 'Finde alle LKW unter 30.000 €', + 'ki.beispiel3': 'Verkaufe Fahrzeug FIN W0LPEHAZ1S8012345 an Müller GmbH', + 'ki.beispiel4': 'Erstelle Kaufvertrag für Fahrzeug FIN W0LPEHAZ1S8012345 an Müller GmbH', + // Common + 'common.laden': 'Laden...', + 'common.speichern': 'Speichern', + 'common.abbrechen': 'Abbrechen', + 'common.schliessen': 'Schließen', + 'common.ja': 'Ja', + 'common.nein': 'Nein', + 'common.bestaetigen': 'Bestätigen', + 'common.loeschen': 'Löschen', + 'common.bearbeiten': 'Bearbeiten', + 'common.suchen': 'Suchen', + 'common.filtern': 'Filtern', + 'common.sortieren': 'Sortieren', + 'common.alle': 'Alle', + 'common.eintraege': 'Einträge', + 'common.von': 'von', + 'common.seite': 'Seite', + 'common.aktion_erfolgreich': 'Aktion erfolgreich', + 'common.fehler_aufgetreten': 'Ein Fehler ist aufgetreten', + 'common.erneut_versuchen': 'Erneut versuchen', + 'common.nicht_verfuegbar': 'Nicht verfügbar', + 'common.aktion_nicht_erlaubt': 'Sie haben keine Berechtigung für diese Aktion', + // Settings + 'set.title': 'Einstellungen', + 'set.stammdaten': 'Stammdaten', + 'set.vertragsvorlagen': 'Vertragsvorlagen', + 'set.benutzerverwaltung': 'Benutzerverwaltung', + 'set.firmenprofil': 'Firmenprofil', + 'set.sprache': 'Sprache', + 'set.design': 'Design', + 'set.dark_mode': 'Dunkler Modus', + }, + en: { + 'nav.dashboard': 'Dashboard', + 'nav.fahrzeuge': 'Vehicle Inventory', + 'nav.fahrzeuge.liste': 'Inventory List', + 'nav.fahrzeuge.neu': 'New Vehicle', + 'nav.kontakte': 'Contacts', + 'nav.verkauf': 'Sales', + 'nav.dateien': 'Files', + 'nav.ki-copilot': 'AI Copilot', + 'nav.einstellungen': 'Settings', + 'nav.benutzerverwaltung': 'User Management', + 'nav.datev': 'DATEV Export', + 'nav.rechnungen': 'Invoices', + 'nav.main': 'Main Menu', + 'nav.verwaltung': 'Administration', + 'nav.ki': 'Artificial Intelligence', + 'topbar.search': 'Search vehicles, contacts, VIN...', + 'topbar.profile': 'Profile', + 'topbar.logout': 'Logout', + 'topbar.role': 'Role', + 'dash.title': 'Dashboard', + 'dash.fahrzeuge_im_bestand': 'Vehicles in Stock', + 'dash.verkaufe_diesen_monat': 'Sales This Month', + 'dash.offene_tasks': 'Open Tasks', + 'dash.mobilede_sync': 'mobile.de Sync Status', + 'dash.schnellzugriffe': 'Quick Actions', + 'dash.neues_fahrzeug': 'Add New Vehicle', + 'dash.neuer_verkauf': 'New Sale', + 'dash.ki_copilot': 'Open AI Copilot', + 'dash.letzte_aktivitaeten': 'Recent Activities', + 'dash.bevorstehende_tasks': 'Upcoming Tasks', + 'dash.verkaeufe_entwicklung': 'Sales Development', + 'dash.top_fahrzeuge': 'Most Requested Vehicles', + 'dash.weiter': 'More', + 'fb.title': 'Vehicle Inventory', + 'fb.suche': 'Search vehicle (make, model, VIN)...', + 'fb.filter': 'Filter', + 'fb.alle': 'All', + 'fb.lkw': 'Truck', + 'fb.baumaschine': 'Construction Machine', + 'fb.transporter': 'Van', + 'fb.add_new': 'Add Vehicle', + 'fb.marke': 'Make', + 'fb.modell': 'Model', + 'fb.fin': 'VIN', + 'fb.baujahr': 'Year', + 'fb.km_stand': 'Mileage', + 'fb.betriebsstunden': 'Operating Hours', + 'fb.preis': 'Price', + 'fb.status': 'Status', + 'fb.mobilede': 'mobile.de', + 'fb.typ': 'Type', + 'fb.standort': 'Location', + 'fb.verfuegbarkeit': 'Availability', + 'fb.verfuegbar': 'Available', + 'fb.reserviert': 'Reserved', + 'fb.verkauft': 'Sold', + 'fb.gelistet': 'Listed', + 'fb.nicht_gelistet': 'Not Listed', + 'fb.fehler': 'Error', + 'fb.aktion': 'Action', + 'fb.bearbeiten': 'Edit', + 'fb.details': 'Details', + 'fb.anzeigen': 'View', + 'fb.keine_fahrzeuge': 'No vehicles found', + 'fb.keine_fahrzeuge_text': 'No vehicles in inventory yet. Add your first vehicle.', + 'fb.fahrzeug_hinzufuegen': 'Add Vehicle', + 'fb.export': 'Export (CSV)', + 'fb.filter_zuruecksetzen': 'Reset Filters', + 'fd.titel': 'Vehicle Details', + 'fd.allgemein': 'General', + 'fd.technische_daten': 'Technical Data', + 'fd.baumaschinen_daten': 'Machine Data', + 'fd.verkaufsinfo': 'Sales Info', + 'fd.dokumente': 'Documents', + 'fd.fotos': 'Photos', + 'fd.mobilede_status': 'mobile.de Status', + 'fd.bearbeiten': 'Edit', + 'fd.verkaufen': 'Sell', + 'fd.zurueck': 'Back to List', + 'fd.hauptfoto': 'Main Photo', + 'fd.keine_fotos': 'No photos available', + 'fd.foto_hochladen': 'Upload Photo', + 'fd.dokument_hochladen': 'Upload Document', + 'fd.kategorie': 'Category', + 'fd.dateiname': 'Filename', + 'fd.groesse': 'Size', + 'fd.upload_datum': 'Upload Date', + 'fd.sync_mobilede': 'Sync to mobile.de', + 'fd.delisting': 'Remove mobile.de Listing', + 'fd.bildretusche': 'AI Photo Retouching', + 'fd.preisvergleich': 'Price Comparison mobile.de', + 'ff.titel_neu': 'Add New Vehicle', + 'ff.titel_bearbeiten': 'Edit Vehicle', + 'ff.speichern': 'Save', + 'ff.abbrechen': 'Cancel', + 'ff.pflichtfeld': 'Required field', + 'ff.ocr_upload': 'OCR Upload (ZB I / ZB II)', + 'ff.ocr_text': 'Photograph vehicle registration or title document and auto-fill data', + 'ff.ocr_ausloesen': 'Start OCR', + 'ff.standard_daten': 'Standard Data', + 'ff.baumaschinen_daten': 'Machine-Specific Data', + 'ff.fahrzeugtyp': 'Vehicle Type', + 'ff.fin_hinweis': '17 characters, unique vehicle identification number', + 'ff.fin_ungueltig': 'VIN must be exactly 17 characters', + 'ff.fin_doppelt': 'VIN already exists', + 'ff.leistung': 'Power (kW)', + 'ff.leistung_ps': 'Power (HP)', + 'ff.kraftstoffart': 'Fuel Type', + 'ff.getriebe': 'Transmission', + 'ff.farbe': 'Color', + 'ff.zustand': 'Condition', + 'ff.erstzulassung': 'First Registration', + 'ff.neu': 'New', + 'ff.gebraucht': 'Used', + 'ff.lkw_typ': 'Truck Type', + 'ff.art': 'Type (Excavator, Wheel Loader, etc.)', + 'ff.aufbau': 'Body/Equipment', + 'ff.betriebsstunden_wert': 'Operating Hours', + 'ff.betriebsstunden_einheit': 'Unit', + 'ff.stunden': 'Hours (h)', + 'ff.minuten': 'Minutes (min)', + 'ff.manuell': 'Manual', + 'ff.automatik': 'Automatic', + 'ff.diesel': 'Diesel', + 'ff.benzin': 'Petrol', + 'ff.elektro': 'Electric', + 'ff.hybrid': 'Hybrid', + 'kt.title': 'Contact & Customer Management', + 'kt.suche': 'Search contacts (name, company, country)...', + 'kt.add_new': 'New Contact', + 'kt.firmenname': 'Company Name', + 'kt.ansprechpartner': 'Contact Person', + 'kt.land': 'Country', + 'kt.rolle': 'Role', + 'kt.ust_id': 'VAT ID', + 'kt.ust_status': 'VAT Status', + 'kt.geprueft': 'Verified', + 'kt.ungeprueft': 'Unverified', + 'kt.manuell_best': 'Manually Confirmed', + 'kt.kaeufer': 'Buyer', + 'kt.verkaeufer': 'Seller', + 'kt.beides': 'Buyer & Seller', + 'kt.detail': 'Detail', + 'kt.keine_kontakte': 'No contacts found', + 'kt.keine_kontakte_text': 'No contacts have been added yet.', + 'kt.neuer_kontakt': 'Add New Contact', + 'vk.title': 'Sales Module', + 'vk.neuer_verkauf': 'New Sale', + 'vk.fahrzeug': 'Vehicle', + 'vk.kaeufer': 'Buyer', + 'vk.verkaeufer': 'Seller', + 'vk.preis': 'Price', + 'vk.zahlungsart': 'Payment Method', + 'vk.uebergabedatum': 'Handover Date', + 'vk.vertragsart': 'Contract Type', + 'vk.inland': 'EU Domestic', + 'vk.eu_ausland': 'EU Foreign', + 'vk.drittland': 'Third Country', + 'vk.kaufvertrag': 'Create Purchase Contract', + 'vk.rechnung': 'Create Invoice', + 'vk.lieferbescheinigung': 'Delivery Certificate', + 'vk.ust_pruefung': 'VAT ID Verification', + 'vk.gwG_warnung': 'AML Warning: Cash payment over 10,000 €', + 'vk.gwG_meldung': 'Reporting obligation under GwG (§ 11 GwG) - Cash payment exceeds 10,000 €', + 'vk.identifikation': 'Partner Identification', + 'vk.ausweis_typ': 'ID Type', + 'vk.ausweis_nr': 'ID Number', + 'vk.ausstellungsland': 'Issuing Country', + 'vk.datum': 'Date', + 'vk.barzahlung': 'Cash', + 'vk.ueberweisung': 'Bank Transfer', + 'vk.speichern': 'Save Sale', + 'vk.pdf_generieren': 'Generate PDF', + 'ki.title': 'AI Copilot', + 'ki.placeholder': 'Ask the AI assistant... (e.g. "Add new vehicle: MAN TGL 2018, 120000 km, 32000 €")', + 'ki.senden': 'Send', + 'ki.spracheingabe': 'Voice Input', + 'ki.historie': 'History', + 'ki.beispiele': 'Example Commands', + 'ki.beispiel1': 'Add new vehicle: Mercedes Actros 2019, 150000 km, 45000 €', + 'ki.beispiel2': 'Find all trucks under 30,000 €', + 'ki.beispiel3': 'Sell vehicle VIN W0LPEHAZ1S8012345 to Müller GmbH', + 'ki.beispiel4': 'Create purchase contract for vehicle VIN W0LPEHAZ1S8012345 to Müller GmbH', + 'common.laden': 'Loading...', + 'common.speichern': 'Save', + 'common.abbrechen': 'Cancel', + 'common.schliessen': 'Close', + 'common.ja': 'Yes', + 'common.nein': 'No', + 'common.bestaetigen': 'Confirm', + 'common.loeschen': 'Delete', + 'common.bearbeiten': 'Edit', + 'common.suchen': 'Search', + 'common.filtern': 'Filter', + 'common.sortieren': 'Sort', + 'common.alle': 'All', + 'common.eintraege': 'entries', + 'common.von': 'of', + 'common.seite': 'Page', + 'common.aktion_erfolgreich': 'Action successful', + 'common.fehler_aufgetreten': 'An error occurred', + 'common.erneut_versuchen': 'Try Again', + 'common.nicht_verfuegbar': 'Not available', + 'common.aktion_nicht_erlaubt': 'You do not have permission for this action', + 'set.title': 'Settings', + 'set.stammdaten': 'Master Data', + 'set.vertragsvorlagen': 'Contract Templates', + 'set.benutzerverwaltung': 'User Management', + 'set.firmenprofil': 'Company Profile', + 'set.sprache': 'Language', + 'set.design': 'Design', + 'set.dark_mode': 'Dark Mode', + } +}; + +// State Management +let currentLang = localStorage.getItem('erp-lang') || 'de'; +let currentRole = localStorage.getItem('erp-role') || 'admin'; +let darkMode = localStorage.getItem('erp-dark') === 'true'; + +function t(key) { + const lang = currentLang; + return (translations[lang] && translations[lang][key]) || translations.de[key] || key; +} + +function setLang(lang) { + currentLang = lang; + localStorage.setItem('erp-lang', lang); + document.documentElement.lang = lang; + applyTranslations(); + updateLangSwitcher(); +} + +function applyTranslations() { + document.querySelectorAll('[data-i18n]').forEach(el => { + const key = el.getAttribute('data-i18n'); + el.textContent = t(key); + }); + document.querySelectorAll('[data-i18n-placeholder]').forEach(el => { + const key = el.getAttribute('data-i18n-placeholder'); + el.placeholder = t(key); + }); + document.querySelectorAll('[data-i18n-title]').forEach(el => { + const key = el.getAttribute('data-i18n-title'); + el.title = t(key); + }); +} + +function updateLangSwitcher() { + document.querySelectorAll('.lang-btn').forEach(btn => { + btn.classList.toggle('active', btn.dataset.lang === currentLang); + }); +} + +function setRole(role) { + currentRole = role; + localStorage.setItem('erp-role', role); + applyRolePermissions(); + updateRoleSwitcher(); +} + +function applyRolePermissions() { + document.querySelectorAll('[data-role]').forEach(el => { + const roles = el.dataset.role.split(','); + el.style.display = roles.includes(currentRole) ? '' : 'none'; + }); +} + +function updateRoleSwitcher() { + document.querySelectorAll('.role-btn').forEach(btn => { + btn.classList.toggle('active', btn.dataset.role === currentRole); + }); +} + +function toggleDarkMode() { + darkMode = !darkMode; + localStorage.setItem('erp-dark', darkMode); + document.documentElement.setAttribute('data-theme', darkMode ? 'dark' : 'light'); + updateDarkModeToggle(); +} + +function updateDarkModeToggle() { + const toggle = document.getElementById('darkModeToggle'); + if (toggle) toggle.classList.toggle('active', darkMode); +} + +function toggleSidebar() { + const sidebar = document.querySelector('.sidebar'); + const overlay = document.querySelector('.sidebar-overlay'); + if (sidebar) sidebar.classList.toggle('open'); + if (overlay) overlay.classList.toggle('show'); +} + +function closeSidebar() { + const sidebar = document.querySelector('.sidebar'); + const overlay = document.querySelector('.sidebar-overlay'); + if (sidebar) sidebar.classList.remove('open'); + if (overlay) overlay.classList.remove('show'); +} + +// Format helpers +function formatPrice(price, lang) { + const l = lang || currentLang; + return new Intl.NumberFormat(l === 'de' ? 'de-DE' : 'en-US', { + style: 'currency', currency: 'EUR', minimumFractionDigits: 0, maximumFractionDigits: 0 + }).format(price); +} + +function formatNumber(num, lang) { + const l = lang || currentLang; + return new Intl.NumberFormat(l === 'de' ? 'de-DE' : 'en-US').format(num); +} + +function formatDate(dateStr, lang) { + const l = lang || currentLang; + const d = new Date(dateStr); + return new Intl.DateTimeFormat(l === 'de' ? 'de-DE' : 'en-US', { + day: '2-digit', month: '2-digit', year: 'numeric' + }).format(d); +} + +// Init on page load +document.addEventListener('DOMContentLoaded', () => { + document.documentElement.lang = currentLang; + if (darkMode) document.documentElement.setAttribute('data-theme', 'dark'); + applyTranslations(); + applyRolePermissions(); + updateLangSwitcher(); + updateRoleSwitcher(); + updateDarkModeToggle(); +}); diff --git a/ui-prototyp/style.css b/ui-prototyp/style.css new file mode 100644 index 0000000..165bee8 --- /dev/null +++ b/ui-prototyp/style.css @@ -0,0 +1,2086 @@ +/* ============================================ + ERP Nutzfahrzeuge - Design Tokens + ============================================ */ +:root { + /* Brand Colors */ + --color-primary: #1e40af; + --color-primary-hover: #1e3a8a; + --color-primary-light: #dbeafe; + --color-primary-dark: #1e3a8a; + --color-secondary: #475569; + --color-accent: #f59e0b; + + /* Status Colors */ + --color-success: #16a34a; + --color-success-light: #dcfce7; + --color-warning: #f59e0b; + --color-warning-light: #fef3c7; + --color-error: #dc2626; + --color-error-light: #fee2e2; + --color-info: #0ea5e9; + --color-info-light: #e0f2fe; + + /* Surface Colors */ + --color-bg: #f8fafc; + --color-surface: #ffffff; + --color-surface-hover: #f1f5f9; + --color-surface-active: #e2e8f0; + --color-border: #e2e8f0; + --color-border-strong: #cbd5e1; + + /* Text Colors */ + --color-text: #0f172a; + --color-text-secondary: #64748b; + --color-text-muted: #94a3b8; + --color-text-inverse: #ffffff; + + /* Typography */ + --font-family: 'Inter', -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; + --font-mono: 'JetBrains Mono', 'Fira Code', monospace; + --font-size-xs: 0.75rem; + --font-size-sm: 0.875rem; + --font-size-base: 1rem; + --font-size-lg: 1.125rem; + --font-size-xl: 1.25rem; + --font-size-2xl: 1.5rem; + --font-size-3xl: 1.875rem; + --font-size-4xl: 2.25rem; + --font-weight-normal: 400; + --font-weight-medium: 500; + --font-weight-semibold: 600; + --font-weight-bold: 700; + --line-height-tight: 1.25; + --line-height-normal: 1.5; + --line-height-relaxed: 1.75; + + /* Spacing (4px base) */ + --space-1: 0.25rem; + --space-2: 0.5rem; + --space-3: 0.75rem; + --space-4: 1rem; + --space-5: 1.25rem; + --space-6: 1.5rem; + --space-8: 2rem; + --space-10: 2.5rem; + --space-12: 3rem; + --space-16: 4rem; + + /* Border Radius */ + --radius-sm: 0.25rem; + --radius-md: 0.375rem; + --radius-lg: 0.5rem; + --radius-xl: 0.75rem; + --radius-full: 9999px; + + /* Shadows */ + --shadow-sm: 0 1px 2px 0 rgba(0,0,0,0.05); + --shadow-md: 0 4px 6px -1px rgba(0,0,0,0.1), 0 2px 4px -2px rgba(0,0,0,0.1); + --shadow-lg: 0 10px 15px -3px rgba(0,0,0,0.1), 0 4px 6px -4px rgba(0,0,0,0.1); + --shadow-xl: 0 20px 25px -5px rgba(0,0,0,0.1), 0 8px 10px -6px rgba(0,0,0,0.1); + + /* Transitions */ + --transition-fast: 150ms ease; + --transition-normal: 250ms ease; + --transition-slow: 350ms ease; + + /* Layout */ + --sidebar-width: 260px; + --sidebar-collapsed: 64px; + --topbar-height: 64px; + + /* Z-Index */ + --z-sidebar: 30; + --z-topbar: 40; + --z-dropdown: 50; + --z-modal: 100; + --z-toast: 200; +} + +/* Dark Mode */ +[data-theme="dark"] { + --color-bg: #0f172a; + --color-surface: #1e293b; + --color-surface-hover: #334155; + --color-surface-active: #475569; + --color-border: #334155; + --color-border-strong: #475569; + --color-text: #f1f5f9; + --color-text-secondary: #94a3b8; + --color-text-muted: #64748b; + --color-primary-light: #1e3a8a; + --color-success-light: #14532d; + --color-warning-light: #78350f; + --color-error-light: #7f1d1d; + --color-info-light: #0c4a6e; +} + +/* Base Reset */ +* { box-sizing: border-box; margin: 0; padding: 0; } +html { font-size: 16px; } +body { + font-family: var(--font-family); + background: var(--color-bg); + color: var(--color-text); + line-height: var(--line-height-normal); + -webkit-font-smoothing: antialiased; +} + +/* Skip Link */ +.skip-link { + position: absolute; + top: -100px; + left: 0; + background: var(--color-primary); + color: white; + padding: var(--space-2) var(--space-4); + border-radius: 0 0 var(--radius-md) 0; + z-index: var(--z-toast); + text-decoration: none; +} +.skip-link:focus { top: 0; } + +/* Focus Ring */ +*:focus-visible { + outline: 2px solid var(--color-primary); + outline-offset: 2px; +} + +/* Scrollbar */ +::-webkit-scrollbar { width: 8px; height: 8px; } +::-webkit-scrollbar-track { background: transparent; } +::-webkit-scrollbar-thumb { background: var(--color-border-strong); border-radius: var(--radius-full); } +::-webkit-scrollbar-thumb:hover { background: var(--color-text-muted); } + +/* App Layout */ +.app-layout { + display: flex; + min-height: 100vh; +} + +/* Sidebar */ +.sidebar { + width: var(--sidebar-width); + background: var(--color-surface); + border-right: 1px solid var(--color-border); + display: flex; + flex-direction: column; + position: fixed; + top: 0; + left: 0; + bottom: 0; + z-index: var(--z-sidebar); + transition: transform var(--transition-normal); +} +.sidebar.collapsed { transform: translateX(-100%); } +.sidebar-header { + height: var(--topbar-height); + display: flex; + align-items: center; + padding: 0 var(--space-6); + border-bottom: 1px solid var(--color-border); + gap: var(--space-3); +} +.sidebar-logo { + width: 32px; height: 32px; + background: var(--color-primary); + border-radius: var(--radius-md); + display: flex; align-items: center; justify-content: center; + color: white; font-weight: var(--font-weight-bold); font-size: var(--font-size-base); +} +.sidebar-title { font-weight: var(--font-weight-bold); font-size: var(--font-size-base); color: var(--color-text); } +.sidebar-subtitle { font-size: var(--font-size-xs); color: var(--color-text-muted); } +.sidebar-nav { + flex: 1; + overflow-y: auto; + padding: var(--space-4) var(--space-3); +} +.sidebar-nav-section { margin-bottom: var(--space-6); } +.sidebar-nav-label { + font-size: var(--font-size-xs); + text-transform: uppercase; + letter-spacing: 0.05em; + color: var(--color-text-muted); + padding: 0 var(--space-3) var(--space-2); + font-weight: var(--font-weight-semibold); +} +.sidebar-nav-item { + display: flex; + align-items: center; + gap: var(--space-3); + padding: var(--space-2) var(--space-3); + border-radius: var(--radius-md); + color: var(--color-text-secondary); + cursor: pointer; + transition: all var(--transition-fast); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-medium); + text-decoration: none; + margin-bottom: 2px; +} +.sidebar-nav-item:hover { background: var(--color-surface-hover); color: var(--color-text); } +.sidebar-nav-item.active { background: var(--color-primary); color: white; } +.sidebar-nav-item.disabled { opacity: 0.4; cursor: not-allowed; } +.sidebar-footer { + padding: var(--space-4) var(--space-3); + border-top: 1px solid var(--color-border); +} + +/* Main Content */ +.main-content { + flex: 1; + margin-left: var(--sidebar-width); + display: flex; + flex-direction: column; + min-height: 100vh; + transition: margin var(--transition-normal); +} +.main-content.sidebar-collapsed { margin-left: 0; } + +/* Topbar */ +.topbar { + height: var(--topbar-height); + background: var(--color-surface); + border-bottom: 1px solid var(--color-border); + display: flex; + align-items: center; + padding: 0 var(--space-6); + gap: var(--space-4); + position: sticky; + top: 0; + z-index: var(--z-topbar); +} +.topbar-breadcrumb { + display: flex; + align-items: center; + gap: var(--space-2); + font-size: var(--font-size-sm); + color: var(--color-text-secondary); +} +.topbar-breadcrumb .current { color: var(--color-text); font-weight: var(--font-weight-semibold); } +.topbar-actions { margin-left: auto; display: flex; align-items: center; gap: var(--space-3); } + +/* Content Area */ +.content-area { + flex: 1; + padding: var(--space-6); + max-width: 1600px; + width: 100%; +} + +/* Cards */ +.card { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-sm); +} +.card-header { + padding: var(--space-4) var(--space-6); + border-bottom: 1px solid var(--color-border); + display: flex; + align-items: center; + justify-content: space-between; +} +.card-title { font-size: var(--font-size-lg); font-weight: var(--font-weight-semibold); } +.card-body { padding: var(--space-6); } + +/* KPI Cards */ +.kpi-card { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + padding: var(--space-5); + box-shadow: var(--shadow-sm); + transition: box-shadow var(--transition-fast); +} +.kpi-card:hover { box-shadow: var(--shadow-md); } +.kpi-card .kpi-label { font-size: var(--font-size-sm); color: var(--color-text-secondary); font-weight: var(--font-weight-medium); } +.kpi-card .kpi-value { font-size: var(--font-size-3xl); font-weight: var(--font-weight-bold); margin-top: var(--space-1); } +.kpi-card .kpi-trend { font-size: var(--font-size-xs); margin-top: var(--space-2); display: flex; align-items: center; gap: var(--space-1); } + +/* Badges */ +.badge { + display: inline-flex; + align-items: center; + gap: var(--space-1); + padding: var(--space-1) var(--space-2); + border-radius: var(--radius-full); + font-size: var(--font-size-xs); + font-weight: var(--font-weight-medium); +} +.badge-success { background: var(--color-success-light); color: var(--color-success); } +.badge-warning { background: var(--color-warning-light); color: #92400e; } +.badge-error { background: var(--color-error-light); color: var(--color-error); } +.badge-info { background: var(--color-info-light); color: #075985; } +.badge-neutral { background: var(--color-surface-active); color: var(--color-text-secondary); } +.badge-primary { background: var(--color-primary-light); color: var(--color-primary); } + +/* Table */ +.data-table { + width: 100%; + border-collapse: collapse; + font-size: var(--font-size-sm); +} +.data-table th { + text-align: left; + padding: var(--space-3) var(--space-4); + font-weight: var(--font-weight-semibold); + color: var(--color-text-secondary); + border-bottom: 1px solid var(--color-border); + white-space: nowrap; + cursor: pointer; + user-select: none; +} +.data-table th:hover { color: var(--color-text); } +.data-table td { + padding: var(--space-3) var(--space-4); + border-bottom: 1px solid var(--color-border); + color: var(--color-text); +} +.data-table tbody tr { transition: background var(--transition-fast); } +.data-table tbody tr:hover { background: var(--color-surface-hover); } +.data-table .sortable-icon { opacity: 0.3; margin-left: var(--space-1); } +.data-table .sorted .sortable-icon { opacity: 1; } + +/* Buttons */ +.btn { + display: inline-flex; + align-items: center; + gap: var(--space-2); + padding: var(--space-2) var(--space-4); + border-radius: var(--radius-md); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-medium); + cursor: pointer; + border: 1px solid transparent; + transition: all var(--transition-fast); + text-decoration: none; + white-space: nowrap; +} +.btn:active { transform: scale(0.98); } +.btn:disabled { opacity: 0.5; cursor: not-allowed; } +.btn-primary { background: var(--color-primary); color: white; } +.btn-primary:hover:not(:disabled) { background: var(--color-primary-hover); } +.btn-secondary { background: var(--color-surface); color: var(--color-text); border-color: var(--color-border-strong); } +.btn-secondary:hover:not(:disabled) { background: var(--color-surface-hover); } +.btn-ghost { background: transparent; color: var(--color-text-secondary); } +.btn-ghost:hover:not(:disabled) { background: var(--color-surface-hover); color: var(--color-text); } +.btn-danger { background: var(--color-error); color: white; } +.btn-danger:hover:not(:disabled) { background: #b91c1c; } +.btn-sm { padding: var(--space-1) var(--space-3); font-size: var(--font-size-xs); } +.btn-lg { padding: var(--space-3) var(--space-6); font-size: var(--font-size-base); } + +/* Inputs */ +.input, .select, .textarea { + width: 100%; + padding: var(--space-2) var(--space-3); + border: 1px solid var(--color-border-strong); + border-radius: var(--radius-md); + font-size: var(--font-size-sm); + background: var(--color-surface); + color: var(--color-text); + transition: border-color var(--transition-fast), box-shadow var(--transition-fast); +} +.input:focus, .select:focus, .textarea:focus { + border-color: var(--color-primary); + box-shadow: 0 0 0 3px var(--color-primary-light); + outline: none; +} +.input:disabled { background: var(--color-surface-hover); cursor: not-allowed; } +.input-error { border-color: var(--color-error); } +.input-error:focus { box-shadow: 0 0 0 3px var(--color-error-light); } +.label { + display: block; + font-size: var(--font-size-sm); + font-weight: var(--font-weight-medium); + color: var(--color-text-secondary); + margin-bottom: var(--space-1); +} +.label .required { color: var(--color-error); } +.form-group { margin-bottom: var(--space-4); } +.form-hint { font-size: var(--font-size-xs); color: var(--color-text-muted); margin-top: var(--space-1); } +.form-error { font-size: var(--font-size-xs); color: var(--color-error); margin-top: var(--space-1); } + +/* Tabs */ +.tabs { + display: flex; + gap: var(--space-1); + border-bottom: 2px solid var(--color-border); + margin-bottom: var(--space-6); + overflow-x: auto; +} +.tab { + padding: var(--space-3) var(--space-4); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-medium); + color: var(--color-text-secondary); + cursor: pointer; + border-bottom: 2px solid transparent; + margin-bottom: -2px; + transition: all var(--transition-fast); + white-space: nowrap; +} +.tab:hover { color: var(--color-text); } +.tab.active { color: var(--color-primary); border-bottom-color: var(--color-primary); } + +/* Mobile Menu Button */ +.mobile-menu-btn { + display: none; + background: none; + border: none; + color: var(--color-text); + cursor: pointer; + padding: var(--space-2); +} + +/* Responsive */ +@media (max-width: 768px) { + .sidebar { transform: translateX(-100%); } + .sidebar.open { transform: translateX(0); } + .main-content { margin-left: 0; } + .mobile-menu-btn { display: flex; } + .content-area { padding: var(--space-4); } + .kpi-grid { grid-template-columns: 1fr 1fr !important; } + .data-table { font-size: var(--font-size-xs); } + .data-table th, .data-table td { padding: var(--space-2); } + .hide-mobile { display: none !important; } + .topbar-actions .lang-switcher { display: none; } +} +@media (max-width: 480px) { + .kpi-grid { grid-template-columns: 1fr !important; } +} + +/* Loading Skeleton */ +.skeleton { + background: linear-gradient(90deg, var(--color-surface-hover) 25%, var(--color-surface-active) 50%, var(--color-surface-hover) 75%); + background-size: 200% 100%; + animation: shimmer 1.5s infinite; + border-radius: var(--radius-md); +} +@keyframes shimmer { + 0% { background-position: 200% 0; } + 100% { background-position: -200% 0; } +} + +/* Empty State */ +.empty-state { + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: var(--space-12) var(--space-6); + text-align: center; +} +.empty-state-icon { width: 64px; height: 64px; color: var(--color-text-muted); margin-bottom: var(--space-4); } +.empty-state-title { font-size: var(--font-size-lg); font-weight: var(--font-weight-semibold); margin-bottom: var(--space-2); } +.empty-state-text { font-size: var(--font-size-sm); color: var(--color-text-secondary); max-width: 400px; margin-bottom: var(--space-4); } + +/* Error State */ +.error-state { + display: flex; + flex-direction: column; + align-items: center; + padding: var(--space-12) var(--space-6); + text-align: center; +} +.error-state-icon { width: 48px; height: 48px; color: var(--color-error); margin-bottom: var(--space-4); } + +/* Chat (KI Copilot) */ +.chat-container { + display: flex; + flex-direction: column; + height: 100%; + max-height: 600px; +} +.chat-messages { + flex: 1; + overflow-y: auto; + padding: var(--space-4); + display: flex; + flex-direction: column; + gap: var(--space-4); +} +.chat-message { + display: flex; + gap: var(--space-3); + max-width: 80%; +} +.chat-message.user { margin-left: auto; flex-direction: row-reverse; } +.chat-bubble { + padding: var(--space-3) var(--space-4); + border-radius: var(--radius-lg); + font-size: var(--font-size-sm); +} +.chat-message.assistant .chat-bubble { background: var(--color-surface-hover); } +.chat-message.user .chat-bubble { background: var(--color-primary); color: white; } +.chat-input-area { + border-top: 1px solid var(--color-border); + padding: var(--space-4); + display: flex; + gap: var(--space-2); +} + +/* Avatar */ +.avatar { + width: 32px; height: 32px; + border-radius: var(--radius-full); + background: var(--color-primary); + color: white; + display: flex; + align-items: center; + justify-content: center; + font-size: var(--font-size-sm); + font-weight: var(--font-weight-semibold); + flex-shrink: 0; +} +.avatar-lg { width: 48px; height: 48px; font-size: var(--font-size-lg); } + +/* Select dropdown */ +.select { + appearance: none; + background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='12' height='12' viewBox='0 0 24 24' fill='none' stroke='currentColor' stroke-width='2'%3E%3Cpolyline points='6 9 12 15 18 9'%3E%3C/polyline%3E%3C/svg%3E"); + background-repeat: no-repeat; + background-position: right var(--space-3) center; + padding-right: var(--space-8); +} + +/* Toggle Switch */ +.toggle { + position: relative; + width: 44px; + height: 24px; + background: var(--color-border-strong); + border-radius: var(--radius-full); + cursor: pointer; + transition: background var(--transition-fast); +} +.toggle.active { background: var(--color-primary); } +.toggle::after { + content: ''; + position: absolute; + top: 2px; left: 2px; + width: 20px; height: 20px; + background: white; + border-radius: var(--radius-full); + transition: transform var(--transition-fast); +} +.toggle.active::after { transform: translateX(20px); } + +/* Tooltip */ +.tooltip { + position: relative; +} +.tooltip:hover::after { + content: attr(data-tooltip); + position: absolute; + bottom: 100%; + left: 50%; + transform: translateX(-50%); + background: var(--color-text); + color: var(--color-text-inverse); + padding: var(--space-1) var(--space-2); + border-radius: var(--radius-sm); + font-size: var(--font-size-xs); + white-space: nowrap; + z-index: var(--z-dropdown); + margin-bottom: var(--space-1); +} + +/* Progress Bar */ +.progress-bar { + width: 100%; + height: 8px; + background: var(--color-surface-active); + border-radius: var(--radius-full); + overflow: hidden; +} +.progress-bar-fill { + height: 100%; + background: var(--color-primary); + border-radius: var(--radius-full); + transition: width var(--transition-normal); +} + +/* Modal Overlay */ +.modal-overlay { + position: fixed; + top: 0; left: 0; right: 0; bottom: 0; + background: rgba(0,0,0,0.5); + z-index: var(--z-modal); + display: flex; + align-items: center; + justify-content: center; + padding: var(--space-4); +} +.modal { + background: var(--color-surface); + border-radius: var(--radius-xl); + box-shadow: var(--shadow-xl); + max-width: 600px; + width: 100%; + max-height: 90vh; + overflow-y: auto; +} +.modal-header { + padding: var(--space-6); + border-bottom: 1px solid var(--color-border); + display: flex; + align-items: center; + justify-content: space-between; +} +.modal-body { padding: var(--space-6); } +.modal-footer { + padding: var(--space-4) var(--space-6); + border-top: 1px solid var(--color-border); + display: flex; + justify-content: flex-end; + gap: var(--space-3); +} + +/* Toast */ +.toast-container { + position: fixed; + bottom: var(--space-6); + right: var(--space-6); + z-index: var(--z-toast); + display: flex; + flex-direction: column; + gap: var(--space-2); +} +.toast { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + box-shadow: var(--shadow-lg); + padding: var(--space-4); + display: flex; + align-items: flex-start; + gap: var(--space-3); + min-width: 300px; + max-width: 400px; + animation: slideIn var(--transition-normal); +} +@keyframes slideIn { + from { transform: translateX(100%); opacity: 0; } + to { transform: translateX(0); opacity: 1; } +} +.toast-success { border-left: 4px solid var(--color-success); } +.toast-error { border-left: 4px solid var(--color-error); } +.toast-warning { border-left: 4px solid var(--color-warning); } +.toast-info { border-left: 4px solid var(--color-info); } + +/* Pagination */ +.pagination { + display: flex; + align-items: center; + gap: var(--space-2); + padding: var(--space-4); + justify-content: space-between; +} +.pagination-info { font-size: var(--font-size-sm); color: var(--color-text-secondary); } +.pagination-controls { display: flex; gap: var(--space-1); } +.pagination-btn { + padding: var(--space-1) var(--space-3); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + background: var(--color-surface); + cursor: pointer; + font-size: var(--font-size-sm); + transition: all var(--transition-fast); +} +.pagination-btn:hover:not(:disabled) { background: var(--color-surface-hover); } +.pagination-btn.active { background: var(--color-primary); color: white; border-color: var(--color-primary); } +.pagination-btn:disabled { opacity: 0.4; cursor: not-allowed; } + +/* Image Grid */ +.image-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); + gap: var(--space-4); +} +.image-grid-item { + aspect-ratio: 4/3; + border-radius: var(--radius-md); + overflow: hidden; + border: 1px solid var(--color-border); + position: relative; + cursor: pointer; + transition: transform var(--transition-fast); +} +.image-grid-item:hover { transform: scale(1.02); } +.image-grid-item img { width: 100%; height: 100%; object-fit: cover; } + +/* File Upload Drop Zone */ +.dropzone { + border: 2px dashed var(--color-border-strong); + border-radius: var(--radius-lg); + padding: var(--space-8); + text-align: center; + cursor: pointer; + transition: border-color var(--transition-fast), background var(--transition-fast); +} +.dropzone:hover, .dropzone.dragover { + border-color: var(--color-primary); + background: var(--color-primary-light); +} + +/* Stat Grid */ +.kpi-grid { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(200px, 1fr)); + gap: var(--space-4); +} + +/* Two Column Layout */ +.two-col { + display: grid; + grid-template-columns: 1fr 1fr; + gap: var(--space-6); +} +@media (max-width: 768px) { + .two-col { grid-template-columns: 1fr; } +} + +/* Info Grid */ +.info-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(250px, 1fr)); + gap: var(--space-4); +} +.info-item { + padding: var(--space-3) 0; +} +.info-label { + font-size: var(--font-size-xs); + color: var(--color-text-muted); + text-transform: uppercase; + letter-spacing: 0.03em; + font-weight: var(--font-weight-medium); + margin-bottom: var(--space-1); +} +.info-value { + font-size: var(--font-size-sm); + color: var(--color-text); + font-weight: var(--font-weight-medium); +} + +/* Warning Banner */ +.warning-banner { + background: var(--color-warning-light); + border: 1px solid var(--color-warning); + border-radius: var(--radius-md); + padding: var(--space-4); + display: flex; + align-items: flex-start; + gap: var(--space-3); + margin-bottom: var(--space-4); +} +.warning-banner-icon { color: var(--color-warning); flex-shrink: 0; } + +/* Spinner */ +.spinner { + width: 20px; + height: 20px; + border: 2px solid var(--color-border); + border-top-color: var(--color-primary); + border-radius: 50%; + animation: spin 0.8s linear infinite; +} +@keyframes spin { to { transform: rotate(360deg); } } +.spinner-lg { width: 40px; height: 40px; border-width: 3px; } + +/* Sidebar Overlay (mobile) */ +.sidebar-overlay { + display: none; + position: fixed; + top: 0; left: 0; right: 0; bottom: 0; + background: rgba(0,0,0,0.5); + z-index: 25; +} +@media (max-width: 768px) { + .sidebar-overlay.show { display: block; } +} + +/* ============================================ + v2 Additions: Card View, Calendar, Stammdaten + ============================================ */ + +/* View Toggle */ +.view-toggle { + display: inline-flex; + border: 1px solid var(--color-border-strong); + border-radius: var(--radius-md); + overflow: hidden; +} +.view-toggle-btn { + padding: var(--space-2) var(--space-3); + background: var(--color-surface); + border: none; + cursor: pointer; + font-size: var(--font-size-sm); + color: var(--color-text-secondary); + display: flex; + align-items: center; + gap: var(--space-2); + transition: all var(--transition-fast); +} +.view-toggle-btn:hover { background: var(--color-surface-hover); } +.view-toggle-btn.active { background: var(--color-primary); color: white; } + +/* Vehicle Cards Grid */ +.card-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(280px, 1fr)); + gap: var(--space-4); +} +.vehicle-card { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + overflow: hidden; + cursor: pointer; + transition: box-shadow var(--transition-fast), transform var(--transition-fast); +} +.vehicle-card:hover { box-shadow: var(--shadow-lg); transform: translateY(-2px); } +.vehicle-card-image { + width: 100%; + aspect-ratio: 4/3; + background: linear-gradient(135deg, var(--color-surface-active), var(--color-border)); + display: flex; + align-items: center; + justify-content: center; + position: relative; +} +.vehicle-card-image .card-status-badge { + position: absolute; + top: var(--space-2); + right: var(--space-2); +} +.vehicle-card-body { padding: var(--space-4); } +.vehicle-card-title { + font-size: var(--font-size-base); + font-weight: var(--font-weight-semibold); + margin-bottom: var(--space-1); +} +.vehicle-card-subtitle { + font-size: var(--font-size-xs); + color: var(--color-text-muted); + font-family: var(--font-mono); + margin-bottom: var(--space-3); +} +.vehicle-card-meta { + display: flex; + justify-content: space-between; + align-items: center; + margin-top: var(--space-2); +} +.vehicle-card-price { + font-size: var(--font-size-lg); + font-weight: var(--font-weight-bold); + color: var(--color-primary); +} +.vehicle-card-info { + font-size: var(--font-size-xs); + color: var(--color-text-secondary); + display: flex; + gap: var(--space-3); + margin-top: var(--space-2); +} + +/* Contact Cards Grid */ +.contact-card { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + padding: var(--space-5); + cursor: pointer; + transition: box-shadow var(--transition-fast), transform var(--transition-fast); +} +.contact-card:hover { box-shadow: var(--shadow-lg); transform: translateY(-2px); } +.contact-card-header { + display: flex; + align-items: flex-start; + gap: var(--space-3); + margin-bottom: var(--space-3); +} +.contact-card-name { + font-size: var(--font-size-base); + font-weight: var(--font-weight-semibold); +} +.contact-card-person { + font-size: var(--font-size-sm); + color: var(--color-text-secondary); +} +.contact-card-info { + display: flex; + flex-direction: column; + gap: var(--space-2); + font-size: var(--font-size-sm); + color: var(--color-text-secondary); +} +.contact-card-info-item { + display: flex; + align-items: center; + gap: var(--space-2); +} + +/* Subtabs (Stammdaten) */ +.subtabs { + display: flex; + gap: var(--space-1); + flex-wrap: wrap; + margin-bottom: var(--space-6); + border-bottom: 1px solid var(--color-border); + padding-bottom: var(--space-2); +} +.subtab { + padding: var(--space-2) var(--space-4); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-medium); + color: var(--color-text-secondary); + cursor: pointer; + border-radius: var(--radius-md); + transition: all var(--transition-fast); + white-space: nowrap; + border: 1px solid transparent; +} +.subtab:hover { background: var(--color-surface-hover); color: var(--color-text); } +.subtab.active { background: var(--color-primary); color: white; } + +/* Stammdaten Table compact */ +.stammdaten-table { + width: 100%; + border-collapse: collapse; + font-size: var(--font-size-sm); +} +.stammdaten-table th { + text-align: left; + padding: var(--space-2) var(--space-3); + font-weight: var(--font-weight-semibold); + color: var(--color-text-secondary); + border-bottom: 1px solid var(--color-border); +} +.stammdaten-table td { + padding: var(--space-2) var(--space-3); + border-bottom: 1px solid var(--color-border); +} +.stammdaten-table tbody tr:hover { background: var(--color-surface-hover); } + +/* Calendar */ +.calendar { + width: 100%; + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + overflow: hidden; +} +.calendar-header { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--space-4) var(--space-6); + border-bottom: 1px solid var(--color-border); + background: var(--color-surface); +} +.calendar-title { + font-size: var(--font-size-lg); + font-weight: var(--font-weight-semibold); +} +.calendar-nav { + display: flex; + gap: var(--space-2); + align-items: center; +} +.calendar-grid { + display: grid; + grid-template-columns: repeat(7, 1fr); + background: var(--color-border); + gap: 1px; +} +.calendar-day-header { + padding: var(--space-2) var(--space-1); + text-align: center; + font-size: var(--font-size-xs); + font-weight: var(--font-weight-semibold); + color: var(--color-text-secondary); + background: var(--color-surface); + text-transform: uppercase; +} +.calendar-day { + min-height: 90px; + padding: var(--space-1); + background: var(--color-surface); + font-size: var(--font-size-xs); + display: flex; + flex-direction: column; + cursor: pointer; + transition: background var(--transition-fast); +} +.calendar-day:hover { background: var(--color-surface-hover); } +.calendar-day.other-month { background: var(--color-bg); color: var(--color-text-muted); } +.calendar-day.today { background: var(--color-primary-light); } +.calendar-day-num { + font-weight: var(--font-weight-semibold); + padding: var(--space-1); +} +.calendar-day.today .calendar-day-num { color: var(--color-primary); } +.calendar-events { + display: flex; + flex-direction: column; + gap: 2px; + overflow: hidden; +} +.calendar-event { + padding: 1px var(--space-1); + border-radius: var(--radius-sm); + font-size: 10px; + font-weight: var(--font-weight-medium); + white-space: nowrap; + overflow: hidden; + text-overflow: ellipsis; + cursor: pointer; +} +.calendar-event-verkauf { background: var(--color-success-light); color: var(--color-success); } +.calendar-event-ueberfuehrung { background: var(--color-info-light); color: var(--color-info); } +.calendar-event-lieferung { background: var(--color-warning-light); color: #92400e; } +.calendar-event-termin { background: var(--color-primary-light); color: var(--color-primary); } +.calendar-event-pruefung { background: var(--color-error-light); color: var(--color-error); } + +/* Calendar Legend */ +.calendar-legend { + display: flex; + gap: var(--space-4); + flex-wrap: wrap; + padding: var(--space-3) var(--space-6); + border-top: 1px solid var(--color-border); + background: var(--color-surface); +} +.calendar-legend-item { + display: flex; + align-items: center; + gap: var(--space-2); + font-size: var(--font-size-xs); + color: var(--color-text-secondary); +} +.calendar-legend-dot { + width: 12px; + height: 12px; + border-radius: var(--radius-sm); +} + +/* Event Modal */ +.event-modal-overlay { + position: fixed; + top: 0; left: 0; right: 0; bottom: 0; + background: rgba(0,0,0,0.5); + z-index: var(--z-modal); + display: flex; + align-items: center; + justify-content: center; + padding: var(--space-4); +} + +/* Section Header */ +.section-header { + display: flex; + align-items: center; + justify-content: space-between; + margin-bottom: var(--space-4); +} +.section-header h3 { + font-size: var(--font-size-lg); + font-weight: var(--font-weight-semibold); +} + +/* Stammdaten Section Card */ +.stammdaten-section { + margin-bottom: var(--space-6); +} + +@media (max-width: 768px) { + .card-grid { grid-template-columns: 1fr; } + .calendar-day { min-height: 60px; } + .calendar-event { font-size: 9px; } + .subtab { font-size: var(--font-size-xs); padding: var(--space-1) var(--space-3); } +} + +/* ============================================ + v3 Additions: Image Manager + ============================================ */ + +/* Image Manager */ +.image-manager { + display: flex; + flex-direction: column; + gap: var(--space-4); +} +.image-upload-zone { + border: 2px dashed var(--color-border-strong); + border-radius: var(--radius-lg); + padding: var(--space-6); + text-align: center; + cursor: pointer; + transition: border-color var(--transition-fast), background var(--transition-fast); + display: flex; + flex-direction: column; + align-items: center; + gap: var(--space-2); +} +.image-upload-zone:hover, .image-upload-zone.dragover { + border-color: var(--color-primary); + background: var(--color-primary-light); +} +.image-upload-zone.uploading { + pointer-events: none; + opacity: 0.7; +} +.image-upload-icon { + width: 48px; height: 48px; + color: var(--color-text-muted); +} +.image-gallery { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(160px, 1fr)); + gap: var(--space-4); +} +.image-thumb { + position: relative; + aspect-ratio: 4/3; + border-radius: var(--radius-md); + overflow: hidden; + border: 2px solid var(--color-border); + cursor: pointer; + background: linear-gradient(135deg, var(--color-surface-active), var(--color-border)); + display: flex; + align-items: center; + justify-content: center; + transition: border-color var(--transition-fast), transform var(--transition-fast); +} +.image-thumb:hover { border-color: var(--color-primary); transform: scale(1.02); } +.image-thumb.main-photo { border-color: var(--color-warning); border-width: 3px; } +.image-thumb-placeholder { + color: var(--color-text-muted); + display: flex; + flex-direction: column; + align-items: center; + gap: var(--space-1); +} +.image-thumb-overlay { + position: absolute; + inset: 0; + background: linear-gradient(transparent 50%, rgba(0,0,0,0.7)); + display: flex; + align-items: flex-end; + padding: var(--space-2); + opacity: 0; + transition: opacity var(--transition-fast); +} +.image-thumb:hover .image-thumb-overlay { opacity: 1; } +.image-thumb-actions { + display: flex; + gap: var(--space-1); +} +.image-thumb-action { + width: 28px; height: 28px; + border-radius: var(--radius-sm); + background: rgba(255,255,255,0.9); + border: none; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; + color: var(--color-text); + transition: background var(--transition-fast); +} +.image-thumb-action:hover { background: white; } +.image-thumb-action.danger:hover { background: var(--color-error); color: white; } +.image-thumb-action.star.active { background: var(--color-warning); color: white; } +.image-thumb-category { + position: absolute; + top: var(--space-1); + left: var(--space-1); + padding: 2px var(--space-1); + border-radius: var(--radius-sm); + font-size: 9px; + font-weight: var(--font-weight-semibold); + text-transform: uppercase; + background: rgba(255,255,255,0.9); + color: var(--color-text); +} +.image-thumb-main-badge { + position: absolute; + top: var(--space-1); + right: var(--space-1); + width: 24px; height: 24px; + border-radius: 50%; + background: var(--color-warning); + color: white; + display: flex; + align-items: center; + justify-content: center; +} + +/* Lightbox Modal */ +.lightbox { + position: fixed; + top: 0; left: 0; right: 0; bottom: 0; + background: rgba(0,0,0,0.9); + z-index: var(--z-modal); + display: flex; + flex-direction: column; + align-items: center; + justify-content: center; + padding: var(--space-6); +} +.lightbox-image { + max-width: 90%; + max-height: 80vh; + border-radius: var(--radius-lg); + background: var(--color-surface-active); + display: flex; + align-items: center; + justify-content: center; +} +.lightbox-info { + color: white; + text-align: center; + margin-top: var(--space-4); +} +.lightbox-close { + position: absolute; + top: var(--space-4); + right: var(--space-4); + width: 40px; height: 40px; + border-radius: 50%; + background: rgba(255,255,255,0.2); + border: none; + color: white; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; +} +.lightbox-close:hover { background: rgba(255,255,255,0.3); } +.lightbox-nav { + position: absolute; + top: 50%; + transform: translateY(-50%); + width: 48px; height: 48px; + border-radius: 50%; + background: rgba(255,255,255,0.2); + border: none; + color: white; + cursor: pointer; + display: flex; + align-items: center; + justify-content: center; +} +.lightbox-nav:hover { background: rgba(255,255,255,0.3); } +.lightbox-nav.prev { left: var(--space-4); } +.lightbox-nav.next { right: var(--space-4); } + +/* KI Retusche Modal */ +.retusche-option { + display: flex; + align-items: center; + gap: var(--space-3); + padding: var(--space-3) var(--space-4); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + cursor: pointer; + transition: border-color var(--transition-fast), background var(--transition-fast); +} +.retusche-option:hover { border-color: var(--color-primary); background: var(--color-primary-light); } +.retusche-option.selected { border-color: var(--color-primary); background: var(--color-primary-light); } +.retusche-option-icon { + width: 40px; height: 40px; + border-radius: var(--radius-md); + background: var(--color-primary-light); + color: var(--color-primary); + display: flex; + align-items: center; + justify-content: center; + flex-shrink: 0; +} + +/* Photo Category Select */ +.photo-category-select { + padding: 4px; + border-radius: var(--radius-sm); + border: 1px solid var(--color-border); + font-size: var(--font-size-xs); +} + +/* Drag Handle */ +.drag-handle { + cursor: grab; + position: absolute; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); + color: white; + opacity: 0; + transition: opacity var(--transition-fast); +} +.image-thumb:hover .drag-handle { opacity: 0.6; } + +@media (max-width: 768px) { + .image-gallery { grid-template-columns: repeat(auto-fill, minmax(120px, 1fr)); } + .lightbox-nav { width: 36px; height: 36px; } +} + +/* ============================================ + v4 Additions: Tabbed Form, Dashboard Config + ============================================ */ + +/* Form Tabs */ +.form-tabs { + display: flex; + gap: var(--space-1); + flex-wrap: wrap; + margin-bottom: var(--space-6); + border-bottom: 2px solid var(--color-border); + padding-bottom: var(--space-2); + overflow-x: auto; +} +.form-tab { + padding: var(--space-2) var(--space-4); + font-size: var(--font-size-sm); + font-weight: var(--font-weight-medium); + color: var(--color-text-secondary); + cursor: pointer; + border-radius: var(--radius-md); + transition: all var(--transition-fast); + white-space: nowrap; + border: 1px solid transparent; + display: flex; + align-items: center; + gap: var(--space-2); +} +.form-tab:hover { background: var(--color-surface-hover); color: var(--color-text); } +.form-tab.active { background: var(--color-primary); color: white; } +.form-tab.has-error { color: var(--color-error); } +.form-tab.has-error.active { background: var(--color-error); color: white; } + +/* ZB Field Reference */ +.zb-field-ref { + display: inline-flex; + align-items: center; + gap: 2px; + padding: 1px 4px; + background: var(--color-surface-active); + border-radius: var(--radius-sm); + font-size: 10px; + font-weight: var(--font-weight-semibold); + color: var(--color-text-secondary); + font-family: var(--font-mono); + margin-left: var(--space-1); + vertical-align: middle; +} + +/* Dashboard Config */ +.dashboard-config-btn { + position: absolute; + top: var(--space-2); + right: var(--space-2); +} +.dashboard-widget { + position: relative; + transition: opacity var(--transition-fast); +} +.dashboard-widget.hidden { display: none; } +.dashboard-widget.dragging { opacity: 0.5; } +.dashboard-widget-handle { + position: absolute; + top: var(--space-2); + right: var(--space-2); + cursor: grab; + color: var(--color-text-muted); + opacity: 0; + transition: opacity var(--transition-fast); +} +.dashboard-widget:hover .dashboard-widget-handle { opacity: 1; } + +/* Config Modal Item */ +.config-item { + display: flex; + align-items: center; + justify-content: space-between; + padding: var(--space-3) var(--space-4); + border: 1px solid var(--color-border); + border-radius: var(--radius-md); + margin-bottom: var(--space-2); +} +.config-item-label { font-size: var(--font-size-sm); font-weight: var(--font-weight-medium); } + +/* File Input Button */ +.file-input-wrapper { + position: relative; + display: inline-block; +} +.file-input-wrapper input[type=file] { + position: absolute; + top: 0; left: 0; + width: 100%; + height: 100%; + opacity: 0; + cursor: pointer; +} + +/* Compact Info Grid (for more fields) */ +.compact-grid { + display: grid; + grid-template-columns: repeat(auto-fill, minmax(200px, 1fr)); + gap: var(--space-3); +} +.compact-grid .form-group { margin-bottom: 0; } + +/* 3-column layout for wider forms */ +.three-col { + display: grid; + grid-template-columns: repeat(3, 1fr); + gap: var(--space-4); +} +@media (max-width: 1024px) { + .three-col { grid-template-columns: 1fr 1fr; } +} +@media (max-width: 768px) { + .three-col { grid-template-columns: 1fr; } +} + +/* Form Section Title */ +.form-section-title { + font-size: var(--font-size-sm); + font-weight: var(--font-weight-semibold); + color: var(--color-text-secondary); + text-transform: uppercase; + letter-spacing: 0.03em; + margin-bottom: var(--space-3); + padding-bottom: var(--space-2); + border-bottom: 1px solid var(--color-border); +} + +/* ============================================ + v6 Mobile Responsive Fixes + ============================================ */ + +/* Mobile-optimized base */ +@media (max-width: 768px) { + html { font-size: 14px; } + body { font-size: 14px; -webkit-text-size-adjust: 100%; } + + /* Content area reduced padding */ + .content-area { padding: var(--space-3); } + + /* Topbar */ + .topbar { padding: 0 var(--space-3); height: 56px; } + .topbar-breadcrumb { font-size: var(--font-size-xs); } + .topbar-breadcrumb span:first-child { display: none; } + .topbar-actions { gap: var(--space-1); } + .topbar-actions .lang-switcher { display: flex; } + .topbar-actions .lang-switcher .btn { min-width: 32px; padding: var(--space-1); } + .topbar-actions .btn { min-width: 36px; min-height: 36px; padding: var(--space-1); } + + /* Sidebar overlay */ + .sidebar { width: 280px; z-index: 100; box-shadow: var(--shadow-xl); } + .sidebar-overlay { display: none; position: fixed; inset: 0; background: rgba(0,0,0,0.5); z-index: 90; } + .sidebar-overlay.show { display: block; } + + /* Main content full width on mobile */ + .main-content { margin-left: 0; } + + /* Hamburger button visible */ + .mobile-menu-btn { display: flex; align-items: center; justify-content: center; min-width: 44px; min-height: 44px; } + + /* KPI cards: 2 columns on mobile */ + .kpi-grid { grid-template-columns: 1fr 1fr; gap: var(--space-3); } + .kpi-card { padding: var(--space-3); } + .kpi-card .kpi-value { font-size: var(--font-size-xl); } + .kpi-card .kpi-label { font-size: var(--font-size-xs); } + .kpi-card .kpi-trend { font-size: 10px; } + + /* Cards */ + .card { border-radius: var(--radius-md); } + .card-header { padding: var(--space-3); } + .card-body { padding: var(--space-3); } + .card-title { font-size: var(--font-size-base); } + + /* Two-col becomes single col */ + .two-col { grid-template-columns: 1fr; gap: var(--space-4); } + .three-col { grid-template-columns: 1fr; } + + /* Tables: horizontal scroll */ + .data-table { font-size: var(--font-size-xs); width: max-content; min-width: 100%; } + .data-table th, .data-table td { padding: var(--space-2); white-space: nowrap; } + .data-table th { font-size: 11px; } + .card-body:has(.data-table) { padding: 0; overflow-x: auto; -webkit-overflow-scrolling: touch; } + + /* Tabs: horizontal scroll */ + .tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; gap: var(--space-1); padding-bottom: var(--space-1); } + .tab { padding: var(--space-2) var(--space-3); font-size: var(--font-size-xs); flex-shrink: 0; } + + /* Form tabs: horizontal scroll */ + .form-tabs { overflow-x: auto; -webkit-overflow-scrolling: touch; flex-wrap: nowrap; padding-bottom: var(--space-2); } + .form-tab { flex-shrink: 0; padding: var(--space-2) var(--space-3); font-size: var(--font-size-xs); } + + /* Subtabs: horizontal scroll */ + .subtabs { overflow-x: auto; -webkit-overflow-scrolling: touch; flex-wrap: nowrap; padding-bottom: var(--space-2); } + .subtab { flex-shrink: 0; font-size: var(--font-size-xs); padding: var(--space-1) var(--space-3); } + + /* Buttons: touch targets */ + .btn { min-height: 40px; padding: var(--space-2) var(--space-3); font-size: var(--font-size-sm); } + .btn-sm { min-height: 36px; min-width: 36px; } + .btn-lg { min-height: 48px; } + + /* Inputs: touch targets */ + .input, .select, .textarea { min-height: 40px; font-size: var(--font-size-sm); padding: var(--space-2); } + + /* Form groups: reduced spacing */ + .form-group { margin-bottom: var(--space-3); } + + /* Info grid: 2 columns on mobile */ + .info-grid { grid-template-columns: 1fr 1fr; gap: var(--space-2); } + .info-item { padding: var(--space-1) 0; } + .info-label { font-size: 10px; } + .info-value { font-size: var(--font-size-xs); } + + /* Card grid: single column on small mobile */ + .card-grid { grid-template-columns: 1fr; gap: var(--space-3); } + .vehicle-card-image { aspect-ratio: 16/9; } + .vehicle-card-body { padding: var(--space-3); } + .vehicle-card-title { font-size: var(--font-size-sm); } + .vehicle-card-price { font-size: var(--font-size-base); } + + /* Calendar: smaller cells */ + .calendar-day { min-height: 60px; padding: 2px; } + .calendar-day-num { font-size: 10px; } + .calendar-event { font-size: 8px; padding: 1px 2px; } + .calendar-header { padding: var(--space-2) var(--space-3); } + .calendar-title { font-size: var(--font-size-sm); } + + /* Pagination */ + .pagination { padding: var(--space-2); flex-direction: column; gap: var(--space-2); } + .pagination-info { font-size: var(--font-size-xs); } + .pagination-btn { min-width: 36px; min-height: 36px; } + + /* Modal: full width on mobile */ + .modal { max-width: 100%; max-height: 95vh; border-radius: var(--radius-md); margin: 0; } + .modal-header { padding: var(--space-3); } + .modal-body { padding: var(--space-3); } + .modal-footer { padding: var(--space-3); flex-direction: column-reverse; } + .modal-footer .btn { width: 100%; } + + /* Toast: full width on mobile */ + .toast-container { left: var(--space-2); right: var(--space-2); bottom: var(--space-2); } + .toast { min-width: auto; max-width: 100%; } + + /* Chat */ + .chat-container { max-height: 400px; } + .chat-message { max-width: 90%; } + + /* Dropzone */ + .dropzone { padding: var(--space-4); } + + /* Image gallery */ + .image-gallery { grid-template-columns: repeat(auto-fill, minmax(100px, 1fr)); gap: var(--space-2); } + .image-thumb-action { width: 24px; height: 24px; } + + /* Lightbox nav */ + .lightbox-nav { width: 36px; height: 36px; } + + /* Headings */ + h1 { font-size: var(--font-size-xl) !important; } + h2 { font-size: var(--font-size-lg) !important; } + h3 { font-size: var(--font-size-base) !important; } + + /* View toggle */ + .view-toggle-btn { padding: var(--space-1) var(--space-2); font-size: var(--font-size-xs); min-height: 36px; } + + /* Stammdaten table */ + .stammdaten-table { font-size: var(--font-size-xs); } + .stammdaten-table th, .stammdaten-table td { padding: var(--space-1) var(--space-2); white-space: nowrap; } + + /* ZB field ref badges */ + .zb-field-ref { font-size: 9px; padding: 1px 2px; } + + /* Compact grid on mobile */ + .compact-grid { grid-template-columns: 1fr; } +} + +/* Very small mobile (< 400px) */ +@media (max-width: 400px) { + .kpi-grid { grid-template-columns: 1fr; } + .info-grid { grid-template-columns: 1fr; } + .content-area { padding: var(--space-2); } + .topbar { padding: 0 var(--space-2); } + .card-body { padding: var(--space-2); } +} + +/* Touch-friendly scrollbar */ +@media (max-width: 768px) { + ::-webkit-scrollbar { width: 4px; height: 4px; } + ::-webkit-scrollbar-thumb { background: var(--color-border-strong); border-radius: 2px; } +} + +/* ============================================ + v7: KI-Copilot ChatGPT Interface + Verkauf List + ============================================ */ + +/* ChatGPT-like Chat Interface */ +.chat-fullscreen { + display: flex; + flex-direction: column; + height: calc(100vh - var(--topbar-height) - 48px); + max-height: 800px; +} +.chat-messages-full { + flex: 1; + overflow-y: auto; + padding: var(--space-4); + display: flex; + flex-direction: column; + gap: var(--space-4); + scroll-behavior: smooth; +} +.chat-bubble-full { + padding: var(--space-3) var(--space-4); + border-radius: var(--radius-lg); + font-size: var(--font-size-sm); + line-height: var(--line-height-relaxed); + max-width: 75%; + white-space: pre-wrap; +} +.chat-msg-user { + display: flex; + justify-content: flex-end; +} +.chat-msg-user .chat-bubble-full { + background: var(--color-primary); + color: white; + border-bottom-right-radius: var(--radius-sm); +} +.chat-msg-ai { + display: flex; + justify-content: flex-start; + gap: var(--space-3); +} +.chat-msg-ai .chat-bubble-full { + background: var(--color-surface-hover); + border-bottom-left-radius: var(--radius-sm); +} +.chat-ai-avatar { + width: 36px; height: 36px; + border-radius: var(--radius-md); + background: var(--color-primary); + color: white; + display: flex; align-items: center; justify-content: center; + flex-shrink: 0; +} + +/* Quick Command Chips */ +.chat-chips { + display: flex; + gap: var(--space-2); + overflow-x: auto; + padding: var(--space-2) 0; + -webkit-overflow-scrolling: touch; +} +.chat-chip { + padding: var(--space-1) var(--space-3); + border-radius: var(--radius-full); + background: var(--color-surface-hover); + border: 1px solid var(--color-border); + font-size: var(--font-size-xs); + font-weight: var(--font-weight-medium); + color: var(--color-text-secondary); + cursor: pointer; + white-space: nowrap; + transition: all var(--transition-fast); + flex-shrink: 0; +} +.chat-chip:hover { + background: var(--color-primary-light); + color: var(--color-primary); + border-color: var(--color-primary); +} + +/* Chat Input Area */ +.chat-input-area-full { + border-top: 1px solid var(--color-border); + padding: var(--space-3); + display: flex; + gap: var(--space-2); + align-items: flex-end; +} +.chat-textarea { + flex: 1; + padding: var(--space-3); + border: 1px solid var(--color-border-strong); + border-radius: var(--radius-lg); + font-size: var(--font-size-sm); + font-family: var(--font-family); + background: var(--color-surface); + color: var(--color-text); + resize: none; + min-height: 48px; + max-height: 200px; + transition: border-color var(--transition-fast); + line-height: var(--line-height-normal); +} +.chat-textarea:focus { + border-color: var(--color-primary); + box-shadow: 0 0 0 3px var(--color-primary-light); + outline: none; +} +.chat-send-btn { + width: 48px; height: 48px; + border-radius: 50%; + background: var(--color-primary); + color: white; + border: none; + cursor: pointer; + display: flex; align-items: center; justify-content: center; + flex-shrink: 0; + transition: all var(--transition-fast); +} +.chat-send-btn:hover { background: var(--color-primary-hover); } +.chat-send-btn:disabled { opacity: 0.5; cursor: not-allowed; } + +/* Mic Button */ +.chat-mic-btn { + width: 48px; height: 48px; + border-radius: 50%; + background: var(--color-surface); + border: 1px solid var(--color-border-strong); + color: var(--color-text-secondary); + cursor: pointer; + display: flex; align-items: center; justify-content: center; + flex-shrink: 0; + transition: all var(--transition-fast); +} +.chat-mic-btn:hover { background: var(--color-surface-hover); } +.chat-mic-btn.recording { + background: var(--color-error); + color: white; + border-color: var(--color-error); + animation: pulse 1.5s infinite; +} +@keyframes pulse { + 0%, 100% { opacity: 1; transform: scale(1); } + 50% { opacity: 0.7; transform: scale(1.1); } +} + +/* Typing Indicator */ +.typing-indicator { + display: flex; + gap: 4px; + padding: var(--space-2) var(--space-3); +} +.typing-dot { + width: 8px; height: 8px; + border-radius: 50%; + background: var(--color-text-muted); + animation: typingBounce 1.4s infinite; +} +.typing-dot:nth-child(2) { animation-delay: 0.2s; } +.typing-dot:nth-child(3) { animation-delay: 0.4s; } +@keyframes typingBounce { + 0%, 60%, 100% { transform: translateY(0); opacity: 0.4; } + 30% { transform: translateY(-8px); opacity: 1; } +} + +/* Verkauf List */ +.verkauf-status-badge { + padding: 2px var(--space-2); + border-radius: var(--radius-full); + font-size: var(--font-size-xs); + font-weight: var(--font-weight-medium); +} +.verkauf-status-entwurf { background: var(--color-surface-active); color: var(--color-text-secondary); } +.verkauf-status-pruefung { background: var(--color-warning-light); color: #92400e; } +.verkauf-status-abgeschlossen { background: var(--color-success-light); color: var(--color-success); } +.verkauf-status-storniert { background: var(--color-error-light); color: var(--color-error); } + +.verkauf-card { + background: var(--color-surface); + border: 1px solid var(--color-border); + border-radius: var(--radius-lg); + padding: var(--space-4); + cursor: pointer; + transition: box-shadow var(--transition-fast), transform var(--transition-fast); +} +.verkauf-card:hover { box-shadow: var(--shadow-md); transform: translateY(-1px); } + +@media (max-width: 768px) { + .chat-fullscreen { height: calc(100vh - 56px - 24px); } + .chat-bubble-full { max-width: 90%; } + .chat-input-area-full { padding: var(--space-2); } + .chat-textarea { min-height: 40px; font-size: var(--font-size-xs); } + .chat-send-btn, .chat-mic-btn { width: 40px; height: 40px; } + .typing-dot { width: 6px; height: 6px; } +} + +/* ============================================ + v8: Fixed-bottom Copilot Chat Layout + ============================================ */ +.copilot-container { + display: flex; + flex-direction: column; + height: calc(100dvh - var(--topbar-height) - 48px); + height: calc(100vh - var(--topbar-height) - 48px); + background: var(--color-bg); +} +.copilot-chat { + flex: 1; + overflow-y: auto; + -webkit-overflow-scrolling: touch; + padding: var(--space-4); + display: flex; + flex-direction: column; + gap: var(--space-4); + scroll-behavior: smooth; +} +.copilot-input-container { + flex-shrink: 0; + border-top: 1px solid var(--color-border); + background: var(--color-surface); + padding: var(--space-3); + position: sticky; + bottom: 0; + z-index: 10; +} +.copilot-chips { + display: flex; + gap: var(--space-2); + overflow-x: auto; + padding: var(--space-2) 0; + -webkit-overflow-scrolling: touch; +} +.copilot-input-row { + display: flex; + gap: var(--space-2); + align-items: flex-end; +} +.copilot-textarea { + flex: 1; + padding: var(--space-3); + border: 1px solid var(--color-border-strong); + border-radius: var(--radius-lg); + font-size: var(--font-size-sm); + font-family: var(--font-family); + background: var(--color-surface); + color: var(--color-text); + resize: none; + min-height: 48px; + max-height: 200px; + line-height: var(--line-height-normal); + transition: border-color var(--transition-fast); +} +.copilot-textarea:focus { + border-color: var(--color-primary); + box-shadow: 0 0 0 3px var(--color-primary-light); + outline: none; +} +@media (max-width: 768px) { + .copilot-container { height: calc(100dvh - 56px); height: calc(100vh - 56px); padding: 0 !important; } + .copilot-chat { padding: var(--space-2); padding-bottom: 0; } + .copilot-input-container { padding: var(--space-2); } + .copilot-textarea { min-height: 40px; font-size: var(--font-size-xs); } + .chat-bubble-full { max-width: 90%; } +} + +/* v8 fix: Content area override for copilot page */ +.content-area.copilot-page, .content-area:has(.copilot-container) { + padding: 0; + max-width: 100%; + overflow: hidden; + display: flex; + flex-direction: column; +} +.content-area.copilot-page > div:first-child, .content-area:has(.copilot-container) > div:first-child { + padding: var(--space-4) var(--space-6) 0; + flex-shrink: 0; +} +.content-area.copilot-page .copilot-container, .content-area:has(.copilot-container) .copilot-container { + height: calc(100vh - var(--topbar-height) - 80px); + flex: 1; + padding: 0 var(--space-6); +} +/* Fallback for browsers without :has() */ +body:has(.copilot-container) .content-area { + padding: 0; + max-width: 100%; + overflow: hidden; +} + +/* ============================================ + v8c: Mobile Copilot Layout Fix (dvh, safe-area) + ============================================ */ + +/* Dynamic viewport height with fallbacks */ +.copilot-container { + height: calc(100vh - var(--topbar-height) - 80px); + height: calc(100dvh - var(--topbar-height) - 80px); +} + +/* Safe area insets */ +.topbar { + padding-top: env(safe-area-inset-top); + height: calc(var(--topbar-height) + env(safe-area-inset-top)); +} +.copilot-input-container { + padding-bottom: calc(var(--space-3) + env(safe-area-inset-bottom)); +} + +/* Mobile-specific copilot (< 768px) */ +@media (max-width: 768px) { + /* Content area: full width, no padding when copilot active */ + .content-area.copilot-page, .content-area:has(.copilot-container) { + padding: 0 !important; + margin: 0 !important; + max-width: 100% !important; + overflow: hidden; + } + .content-area.copilot-page > div:first-child, .content-area:has(.copilot-container) > div:first-child { + padding: var(--space-2) var(--space-3) 0; + } + + /* Copilot container: full height on mobile */ + .copilot-container { + height: calc(100vh - var(--topbar-height) - 60px); + height: calc(100dvh - var(--topbar-height) - 60px); + padding: 0 var(--space-3); + } + + /* Chat area: flex 1 with touch scroll */ + .copilot-chat { + flex: 1; + overflow-y: auto; + -webkit-overflow-scrolling: touch; + padding: var(--space-2); + } + + /* Input container: sticky bottom with safe-area */ + .copilot-input-container { + position: sticky; + bottom: 0; + padding: var(--space-2) var(--space-3); + padding-bottom: calc(var(--space-2) + env(safe-area-inset-bottom)); + background: var(--color-surface); + z-index: 10; + } + + /* Chips: horizontal scroll on mobile */ + .copilot-chips { + overflow-x: auto; + white-space: nowrap; + -webkit-overflow-scrolling: touch; + padding: var(--space-1) 0; + } + .chat-chip { + flex-shrink: 0; + } + + /* Textarea: smaller on mobile */ + .copilot-textarea { + width: 100%; + min-height: 40px; + max-height: 120px; + font-size: var(--font-size-xs); + padding: var(--space-2); + } + + /* Mic and Send: touch targets */ + .chat-mic-btn { + min-width: 40px; + min-height: 40px; + width: 40px; + height: 40px; + } + .chat-send-btn { + min-width: 40px; + min-height: 40px; + width: 40px; + height: 40px; + } + + /* Chat bubbles: wider on mobile */ + .chat-bubble-full { + max-width: 88%; + font-size: var(--font-size-xs); + } + + /* Typing dots: smaller on mobile */ + .typing-dot { + width: 6px; + height: 6px; + } +} + +/* Very small mobile (< 400px) */ +@media (max-width: 400px) { + .copilot-container { + height: calc(100vh - var(--topbar-height) - 50px); + height: calc(100dvh - var(--topbar-height) - 50px); + padding: 0 var(--space-2); + } + .copilot-textarea { + min-height: 36px; + } + .chat-bubble-full { + max-width: 92%; + } +} + + +/* v8d: Reliable copilot mobile fix */ +body.copilot-active .content-area { + padding: 0 !important; + max-width: 100% !important; + overflow: hidden !important; + display: flex !important; + flex-direction: column !important; +} +body.copilot-active .content-area > div:first-child { + padding: var(--space-3) var(--space-4) 0; + flex-shrink: 0; +} +body.copilot-active .content-area .copilot-container { + height: calc(100dvh - var(--topbar-height) - 60px); + height: calc(100vh - var(--topbar-height) - 60px); + flex: 1; + padding: 0 var(--space-4); + max-height: none !important; +} +@media (max-width: 768px) { + body.copilot-active .content-area { + padding: 0 !important; + } + body.copilot-active .content-area > div:first-child { + padding: var(--space-2) var(--space-3) 0; + } + body.copilot-active .content-area .copilot-container { + height: calc(100dvh - 56px - 48px); + height: calc(100vh - 56px - 48px); + padding: 0 var(--space-2); + max-height: none !important; + } + body.copilot-active .copilot-input-container { + padding: var(--space-2) !important; + padding-bottom: calc(var(--space-2) + env(safe-area-inset-bottom)) !important; + } + body.copilot-active .copilot-textarea { + min-height: 44px !important; + font-size: 16px !important; + } + body.copilot-active .copilot-input-row { + gap: var(--space-2); + } +} +@media (max-width: 400px) { + body.copilot-active .content-area .copilot-container { + padding: 0 var(--space-1); + } + body.copilot-active .copilot-textarea { + min-height: 40px !important; + } +}