From 411ee8a241c0740e8e931f02171f187ebdc67559 Mon Sep 17 00:00:00 2001 From: Maaxxs <61059039+MaaxxsDev@users.noreply.github.com> Date: Wed, 8 Jul 2026 10:28:05 +0200 Subject: [PATCH] Add selectable package card color themes and refine the feature list styling Bullet lists on package cards now use accent-colored checkmarks instead of plain browser dots. The card color system is now driven by a persistent site setting (Admin > Einstellungen > Website > "Paket-Kachel-Design") with three curated themes - Graphite Green, Deep Blue Luxury, and Warm Bronze - all converging on the same dark "Onyx + Gold" treatment for the priciest tier, matching the reference mockups. Co-Authored-By: Claude Sonnet 5 --- hifi-src/src/components/PublicLayout.jsx | 1 + .../pages/admin/settings/WebsiteSettings.jsx | 47 +++++++++++- hifi-src/src/pages/public/ModelPage.jsx | 76 +++++++++++++------ .../database/migration_package_card_theme.sql | 7 ++ hifi/api/database/schema.sql | 1 + .../Controllers/SiteSettingsController.php | 13 +++- hifi/api/src/Support/Schema.php | 2 + 7 files changed, 122 insertions(+), 25 deletions(-) create mode 100644 hifi/api/database/migration_package_card_theme.sql diff --git a/hifi-src/src/components/PublicLayout.jsx b/hifi-src/src/components/PublicLayout.jsx index 57e87c1..99b0dea 100644 --- a/hifi-src/src/components/PublicLayout.jsx +++ b/hifi-src/src/components/PublicLayout.jsx @@ -25,6 +25,7 @@ const DEFAULT_SITE_SETTINGS = { contact_email: 'info@hifi-planet-amorbach.de', hero_image_path: null, ga_measurement_id: null, + package_card_theme: 'graphite', }; // Das Impressum (und die anderen rechtlichen Pflichtseiten) müssen laut § 5 DDG diff --git a/hifi-src/src/pages/admin/settings/WebsiteSettings.jsx b/hifi-src/src/pages/admin/settings/WebsiteSettings.jsx index cf41c9c..61d16b7 100644 --- a/hifi-src/src/pages/admin/settings/WebsiteSettings.jsx +++ b/hifi-src/src/pages/admin/settings/WebsiteSettings.jsx @@ -2,7 +2,20 @@ import { useEffect, useState } from 'react'; import { api } from '../../../api/client.js'; import ImageUploadField from '../../../components/ImageUploadField.jsx'; -const emptyForm = { phone: '', whatsapp: '', contact_email: '', hero_image_path: '', ga_measurement_id: '' }; +const emptyForm = { + phone: '', + whatsapp: '', + contact_email: '', + hero_image_path: '', + ga_measurement_id: '', + package_card_theme: 'graphite', +}; + +const PACKAGE_CARD_THEMES = [ + { value: 'graphite', label: 'Graphite Green', description: 'Graphit über Bronze/Silber/Gold/Platin bis zur Onyx-Krönung.' }, + { value: 'deep-blue', label: 'Deep Blue Luxury', description: 'Kühles Blau, das sich über Grün zu Gold erwärmt.' }, + { value: 'warm-bronze', label: 'Warm Bronze', description: 'Durchgehend warmes Kupfer/Bronze/Amber bis zum Gold.' }, +]; export default function WebsiteSettings() { const [form, setForm] = useState(emptyForm); @@ -28,6 +41,7 @@ export default function WebsiteSettings() { contact_email: res.contact_email || '', hero_image_path: res.hero_image_path || '', ga_measurement_id: res.ga_measurement_id || '', + package_card_theme: res.package_card_theme || 'graphite', }) ) .finally(() => setLoading(false)); @@ -134,6 +148,37 @@ export default function WebsiteSettings() { +
+

Paket-Kachel-Design

+

+ Bestimmt die Farbgebung der Paket-Stufen auf jeder Fahrzeug-Modell-Seite (von der günstigsten bis zur + teuersten Option). +

+
+ {PACKAGE_CARD_THEMES.map((theme) => ( + + ))} +
+
+

Google Analytics

diff --git a/hifi-src/src/pages/public/ModelPage.jsx b/hifi-src/src/pages/public/ModelPage.jsx index 862435d..e73cb64 100644 --- a/hifi-src/src/pages/public/ModelPage.jsx +++ b/hifi-src/src/pages/public/ModelPage.jsx @@ -7,26 +7,46 @@ import MaintenanceBypassBanner from '../../components/MaintenanceBypassBanner.js import DynamicIcon from '../../components/DynamicIcon.jsx'; import { useMaintenance } from '../../context/MaintenanceContext.jsx'; import { useLanguage } from '../../context/LanguageContext.jsx'; +import { useSiteSettings } from '../../context/SiteSettingsContext.jsx'; // Material-Stufen statt einfarbigem Verlauf: jede Preisstufe durchlaeuft eine eigene -// "Wertigkeit" wie bei Kreditkarten-/Loyalty-Stufen - Graphit (Einstieg) -> Bronze -> -// Silber -> Gold -> Platin -> Onyx (fast schwarz, mit Gold-Glanz als Kroenung ganz oben). -// Die Paket-Sektion sitzt bewusst IMMER auf einer dunklen Buehne (unabhaengig vom -// Hell/Dunkel-Modus der Seite, wie ein Fahrzeugkonfigurator) - das ist der groesste Hebel -// fuer den edlen/luxurioesen Eindruck, den flache helle Kacheln nicht liefern konnten. -// Jede Stufe hat eine Flaechenfarbe (bg) und eine dazu passende Akzentfarbe (Rahmen/ -// Leucht-Schatten/Preis/Icon) - nur der "Kontakt anfragen"-Button bleibt ueberall -// einheitlich markengruen, damit die Kernaktion auf jeder Karte wiedererkennbar bleibt. -// Zwischen zwei Nachbar-Materialien wird in RGB linear interpoliert (siehe materialRgbAt), -// sodass JEDES Paket (nicht nur die Materialien selbst) eine eigene Abstufung bekommt. -const MATERIALS = [ - { bg: [0, 0, 14], accent: [88, 45, 55] }, // Graphit (Einstieg) - { bg: [24, 32, 22], accent: [24, 55, 58] }, // Bronze - { bg: [212, 10, 24], accent: [212, 18, 68] }, // Silber - { bg: [45, 38, 24], accent: [42, 68, 58] }, // Gold - { bg: [196, 12, 27], accent: [200, 20, 72] }, // Platin - { bg: [225, 22, 5], accent: [45, 78, 68] }, // Onyx -]; +// "Wertigkeit" wie bei Kreditkarten-/Loyalty-Stufen. Die Paket-Sektion sitzt bewusst IMMER +// auf einer dunklen Buehne (unabhaengig vom Hell/Dunkel-Modus der Seite, wie ein +// Fahrzeugkonfigurator) - das ist der groesste Hebel fuer den edlen/luxurioesen Eindruck, +// den flache helle Kacheln nicht liefern konnten. Jede Stufe hat eine Flaechenfarbe (bg) +// und eine dazu passende Akzentfarbe (Rahmen/Leucht-Schatten/Preis/Icon) - nur der +// "Kontakt anfragen"-Button bleibt ueberall einheitlich markengruen, damit die Kernaktion +// auf jeder Karte wiedererkennbar bleibt. Zwischen zwei Nachbar-Materialien wird in RGB +// linear interpoliert (siehe materialRgbAt), sodass JEDES Paket (nicht nur die Materialien +// selbst) eine eigene Abstufung bekommt. Welches Farbschema verwendet wird, waehlt der +// Kunde selbst unter Admin -> Einstellungen -> Website ("Paket-Kachel-Design") - alle drei +// laufen bewusst auf dieselbe Onyx+Gold-Kroenung bei der teuersten Stufe zu. +const PACKAGE_THEMES = { + graphite: [ + { bg: [0, 0, 14], accent: [88, 45, 55] }, // Graphit (Einstieg) + { bg: [24, 32, 22], accent: [24, 55, 58] }, // Bronze + { bg: [212, 10, 24], accent: [212, 18, 68] }, // Silber + { bg: [45, 38, 24], accent: [42, 68, 58] }, // Gold + { bg: [196, 12, 27], accent: [200, 20, 72] }, // Platin + { bg: [225, 22, 5], accent: [45, 78, 68] }, // Onyx + ], + 'deep-blue': [ + { bg: [212, 30, 16], accent: [205, 45, 62] }, // Eisblau (Einstieg) + { bg: [212, 35, 20], accent: [205, 50, 64] }, // Tiefblau + { bg: [190, 30, 22], accent: [190, 45, 62] }, // Petrol + { bg: [160, 30, 20], accent: [150, 45, 58] }, // Seegruen + { bg: [95, 30, 20], accent: [95, 50, 58] }, // Markengruen + { bg: [225, 22, 5], accent: [45, 78, 68] }, // Onyx + ], + 'warm-bronze': [ + { bg: [28, 22, 16], accent: [32, 40, 55] }, // Warmes Graphit (Einstieg) + { bg: [26, 38, 22], accent: [28, 58, 55] }, // Bronze + { bg: [32, 42, 24], accent: [34, 62, 56] }, // Kupfer + { bg: [38, 45, 24], accent: [38, 66, 58] }, // Amber + { bg: [42, 48, 24], accent: [42, 70, 60] }, // Reiches Gold + { bg: [225, 22, 5], accent: [45, 78, 68] }, // Onyx + ], +}; const hslToRgb = (h, s, l) => { s /= 100; @@ -67,6 +87,8 @@ export default function ModelPage() { const [error, setError] = useState(''); const maintenance = useMaintenance(); const { t, language } = useLanguage(); + const { package_card_theme: packageCardTheme } = useSiteSettings(); + const MATERIALS = PACKAGE_THEMES[packageCardTheme] || PACKAGE_THEMES.graphite; const formatPrice = (value) => new Intl.NumberFormat(language === 'de' ? 'de-DE' : 'en-US', { style: 'currency', currency: 'EUR' }).format(value); @@ -257,17 +279,27 @@ export default function ModelPage() {

-