From 8862f0c6b8af75fab68bb8658277147fdc8f420d Mon Sep 17 00:00:00 2001 From: sebseb7 Date: Thu, 4 Sep 2025 05:54:01 +0200 Subject: [PATCH] feat: integrate ventilation selection into GrowTentKonfigurator - Removed unused imports related to ventilation types and updated the product selection logic to dynamically filter ventilation options based on the selected tent shape. - Implemented new methods to retrieve and filter available ventilation products, enhancing the user experience by ensuring only relevant options are displayed. - Updated the UI to reflect the selected tent shape and provide feedback when no matching ventilation products are available. - Improved overall rendering of the ventilation section with better styling and selection indicators. --- src/data/configuratorData.js | 175 -------------------------- src/pages/GrowTentKonfigurator.js | 198 +++++++++++++++++++++++++++--- 2 files changed, 182 insertions(+), 191 deletions(-) diff --git a/src/data/configuratorData.js b/src/data/configuratorData.js index 4fec079..3b529fa 100644 --- a/src/data/configuratorData.js +++ b/src/data/configuratorData.js @@ -42,181 +42,6 @@ export const tentShapes = [ } ]; -export const tentSizes = [ - // 60x60 tents - { - id: 'tent_60x60x140', - name: 'Basic 140cm', - description: 'Einsteigermodell', - price: 89.99, - image: '/assets/images/nopicture.jpg', - dimensions: '60x60x140cm', - coverage: '1-2 Pflanzen', - shapeId: '60x60', - height: 140 - }, - { - id: 'tent_60x60x160', - name: 'Premium 160cm', - description: 'Mehr Höhe für größere Pflanzen', - price: 109.99, - image: '/assets/images/nopicture.jpg', - dimensions: '60x60x160cm', - coverage: '1-2 Pflanzen', - shapeId: '60x60', - height: 160 - }, - // 80x80 tents - { - id: 'tent_80x80x160', - name: 'Standard 160cm', - description: 'Beliebtes Mittelklasse-Modell', - price: 129.99, - image: '/assets/images/nopicture.jpg', - dimensions: '80x80x160cm', - coverage: '2-4 Pflanzen', - shapeId: '80x80', - height: 160 - }, - { - id: 'tent_80x80x180', - name: 'Pro 180cm', - description: 'Extra Höhe für optimales Wachstum', - price: 149.99, - image: '/assets/images/nopicture.jpg', - dimensions: '80x80x180cm', - coverage: '2-4 Pflanzen', - shapeId: '80x80', - height: 180 - }, - // 100x100 tents - { - id: 'tent_100x100x180', - name: 'Professional 180cm', - description: 'Für anspruchsvolle Projekte', - price: 189.99, - image: '/assets/images/nopicture.jpg', - dimensions: '100x100x180cm', - coverage: '4-6 Pflanzen', - shapeId: '100x100', - height: 180 - }, - { - id: 'tent_100x100x200', - name: 'Expert 200cm', - description: 'Maximum an Wuchshöhe', - price: 219.99, - image: '/assets/images/nopicture.jpg', - dimensions: '100x100x200cm', - coverage: '4-6 Pflanzen', - shapeId: '100x100', - height: 200 - }, - // 120x60 tents - { - id: 'tent_120x60x160', - name: 'Rectangular 160cm', - description: 'Platzsparend und effizient', - price: 139.99, - image: '/assets/images/nopicture.jpg', - dimensions: '120x60x160cm', - coverage: '3-6 Pflanzen', - shapeId: '120x60', - height: 160 - }, - { - id: 'tent_120x60x180', - name: 'Rectangular Pro 180cm', - description: 'Optimale Raumausnutzung', - price: 169.99, - image: '/assets/images/nopicture.jpg', - dimensions: '120x60x180cm', - coverage: '3-6 Pflanzen', - shapeId: '120x60', - height: 180 - } -]; - -export const lightTypes = [ - { - id: 'led_quantum_board', - name: 'LED Quantum Board', - description: 'Energieeffizient, geringe Wärmeentwicklung', - price: 159.99, - image: '/assets/images/nopicture.jpg', - wattage: '240W', - coverage: 'Bis 100x100cm', - spectrum: 'Vollspektrum', - efficiency: 'Sehr hoch' - }, - { - id: 'led_cob', - name: 'LED COB', - description: 'Hochintensive COB-LEDs', - price: 199.99, - image: '/assets/images/nopicture.jpg', - wattage: '300W', - coverage: 'Bis 120x120cm', - spectrum: 'Vollspektrum', - efficiency: 'Hoch' - }, - { - id: 'hps_400w', - name: 'HPS 400W', - description: 'Bewährte Natriumdampflampe', - price: 89.99, - image: '/assets/images/nopicture.jpg', - wattage: '400W', - coverage: 'Bis 80x80cm', - spectrum: 'Blüte-optimiert', - efficiency: 'Mittel' - }, - { - id: 'cmh_315w', - name: 'CMH 315W', - description: 'Keramik-Metallhalogenid', - price: 129.99, - image: '/assets/images/nopicture.jpg', - wattage: '315W', - coverage: 'Bis 90x90cm', - spectrum: 'Natürlich', - efficiency: 'Hoch' - } -]; - -export const ventilationTypes = [ - { - id: 'basic_exhaust', - name: 'Basic Abluft-Set', - description: 'Lüfter + Aktivkohlefilter', - price: 79.99, - image: '/assets/images/nopicture.jpg', - airflow: '187 m³/h', - noiseLevel: '35 dB', - includes: ['Rohrventilator', 'Aktivkohlefilter', 'Aluflexrohr'] - }, - { - id: 'premium_ventilation', - name: 'Premium Klima-Set', - description: 'Komplette Klimakontrolle', - price: 159.99, - image: '/assets/images/nopicture.jpg', - airflow: '280 m³/h', - noiseLevel: '28 dB', - includes: ['EC-Lüfter', 'Aktivkohlefilter', 'Thermostat', 'Feuchtigkeitsmesser'] - }, - { - id: 'pro_climate', - name: 'Profi Klima-System', - description: 'Automatisierte Klimasteuerung', - price: 299.99, - image: '/assets/images/nopicture.jpg', - airflow: '420 m³/h', - noiseLevel: '25 dB', - includes: ['Digitaler Controller', 'EC-Lüfter', 'Aktivkohlefilter', 'Zu-/Abluft'] - } -]; - export const extras = [ { id: 'ph_tester', diff --git a/src/pages/GrowTentKonfigurator.js b/src/pages/GrowTentKonfigurator.js index d6485dd..94a36ae 100644 --- a/src/pages/GrowTentKonfigurator.js +++ b/src/pages/GrowTentKonfigurator.js @@ -15,8 +15,8 @@ import { CircularProgress, } from '@mui/material'; import ShoppingCartIcon from '@mui/icons-material/ShoppingCart'; -import { TentShapeSelector, ProductSelector, ExtrasSelector } from '../components/configurator/index.js'; -import { tentShapes, ventilationTypes, extras } from '../data/configuratorData.js'; +import { TentShapeSelector, ExtrasSelector } from '../components/configurator/index.js'; +import { tentShapes, extras } from '../data/configuratorData.js'; function setCachedCategoryData(categoryId, data) { if (!window.productCache) { @@ -312,6 +312,58 @@ class GrowTentKonfigurator extends Component { return this.filterLampsByTentSize(shapeId, cachedData.products, cachedData.attributes); } + // Get ventilation products for selected tent shape + getVentilationForTentShape(shapeId) { + const cachedData = getCachedCategoryData('Abluft-sets'); + if (!cachedData || !cachedData.products || !cachedData.attributes) { + console.log('No cached ventilation data available'); + return []; + } + + return this.filterVentilationByTentSize(shapeId, cachedData.products, cachedData.attributes); + } + + // Filter ventilation by tent size using "passend für Zelt" attribute + filterVentilationByTentSize(tentShape, products, attributes) { + if (!products || !attributes || !tentShape) return []; + + console.log('Filtering ventilation for tent shape:', tentShape); + console.log('Available ventilation products:', products.length); + console.log('Available ventilation attributes:', attributes.length); + + // Group attributes by product ID and attribute name + const attributesByProduct = {}; + attributes.forEach(attr => { + if (!attributesByProduct[attr.kArtikel]) { + attributesByProduct[attr.kArtikel] = {}; + } + attributesByProduct[attr.kArtikel][attr.cName] = attr.cWert; + }); + + // Filter products by matching tent size in "passend für Zelt" attribute + const matchingProducts = products.filter(product => { + const attrs = attributesByProduct[product.id]; + if (!attrs) return false; + + // Check "passend für Zelt" attribute + const tentSizeAttr = attrs['passend für Zelt']; + if (!tentSizeAttr) return false; + + // Check if tent size matches + const sizeMatch = tentSizeAttr === tentShape; + + // Check availability - only show products that are available for delivery + const isAvailable = (product.available > 0) || (product.availableSupplier === 1); + + console.log(`Ventilation Product ${product.id}: tentSize=${tentSizeAttr}, match=${sizeMatch}, available=${isAvailable}`); + + return sizeMatch && isAvailable; + }); + + console.log('Filtered ventilation:', matchingProducts.length); + return matchingProducts; + } + // Helper function to generate coverage descriptions getCoverageDescription(width, depth) { const area = width * depth; @@ -423,8 +475,9 @@ class GrowTentKonfigurator extends Component { // Add ventilation price if (selectedVentilationType) { - const ventilation = ventilationTypes.find(v => v.id === selectedVentilationType); - if (ventilation) { + const availableVentilation = this.getVentilationForTentShape(this.state.selectedTentShape); + const ventilation = availableVentilation.find(v => v.id === selectedVentilationType); + if (ventilation && ventilation.price) { total += ventilation.price; itemCount++; } @@ -495,8 +548,9 @@ class GrowTentKonfigurator extends Component { } if (selectedVentilationType) { - const ventilation = ventilationTypes.find(v => v.id === selectedVentilationType); - if (ventilation) { + const availableVentilation = this.getVentilationForTentShape(this.state.selectedTentShape); + const ventilation = availableVentilation.find(v => v.id === selectedVentilationType); + if (ventilation && ventilation.price) { originalTotal += ventilation.price; itemCount++; } @@ -801,17 +855,128 @@ class GrowTentKonfigurator extends Component { } renderVentilationSection() { - const { selectedVentilationType } = this.state; + const { selectedVentilationType, selectedTentShape } = this.state; + if (!selectedTentShape) { + return ( + + + 4. Belüftung auswählen + + + Bitte wählen Sie zuerst eine Zeltgröße aus. + + + ); + } + + // Get real ventilation products for selected tent shape + const availableVentilation = this.getVentilationForTentShape(selectedTentShape); + const cachedData = getCachedCategoryData('Abluft-sets'); + + if (!cachedData) { + return ( + + + 4. Belüftung auswählen - {selectedTentShape} + + + Lade Belüftungs-Produkte... + + + ); + } + + if (availableVentilation.length === 0) { + return ( + + + 4. Belüftung auswählen - {selectedTentShape} + + + Keine passenden Belüftung für Zeltgröße {selectedTentShape} verfügbar. + + + ); + } + return ( - + + + 4. Belüftung auswählen - {selectedTentShape} + + + {availableVentilation.map((ventilation) => ( + + this.handleVentilationSelect(ventilation.id)} + > + {/* Image */} + + {this.renderTentImage(ventilation)} + + + {/* Content */} + + {/* Name */} + + {ventilation.name} + + + {/* Price with VAT */} + + {ventilation.price ? new Intl.NumberFormat('de-DE', { + style: 'currency', + currency: 'EUR' + }).format(ventilation.price) : 'Kein Preis'} + {ventilation.vat && ( + + (incl. {ventilation.vat}% MwSt.,*) + + )} + + + {/* Selection Indicator */} + {selectedVentilationType === ventilation.id && ( + + ✓ Ausgewählt + + )} + + + + ))} + + ); } @@ -843,7 +1008,8 @@ class GrowTentKonfigurator extends Component { } const availableLamps = this.state.selectedTentShape ? this.getLampsForTentShape(this.state.selectedTentShape) : []; const selectedLight = availableLamps.find(l => l.id === selectedLightType); - const selectedVentilation = ventilationTypes.find(v => v.id === selectedVentilationType); + const availableVentilation = this.state.selectedTentShape ? this.getVentilationForTentShape(this.state.selectedTentShape) : []; + const selectedVentilation = availableVentilation.find(v => v.id === selectedVentilationType); const selectedExtrasItems = extras.filter(e => selectedExtras.includes(e.id)); const savingsInfo = this.calculateSavings();