feat: improve ventilation selection logic in GrowTentKonfigurator
- Added functionality to reset ventilation selection when the tent shape changes and the current selection is not deliverable. - Updated product filtering to include all size-matching products while marking their availability status. - Enhanced UI to visually indicate non-deliverable ventilation options, improving user experience and clarity in selection. - Adjusted price calculations to consider only deliverable ventilation products.
This commit is contained in:
@@ -117,6 +117,15 @@ class GrowTentKonfigurator extends Component {
|
|||||||
this.setState({ selectedTentSize: '' });
|
this.setState({ selectedTentSize: '' });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Reset ventilation selection if current selection is not deliverable for new tent shape
|
||||||
|
if (prevState.selectedTentShape !== this.state.selectedTentShape && this.state.selectedVentilationType) {
|
||||||
|
const availableVentilation = this.getVentilationForTentShape(this.state.selectedTentShape);
|
||||||
|
const currentVentilation = availableVentilation.find(v => v.id === this.state.selectedVentilationType);
|
||||||
|
if (!currentVentilation || !currentVentilation.isDeliverable) {
|
||||||
|
this.setState({ selectedVentilationType: '' });
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Recalculate total price when selections change
|
// Recalculate total price when selections change
|
||||||
if (
|
if (
|
||||||
prevState.selectedTentSize !== this.state.selectedTentSize ||
|
prevState.selectedTentSize !== this.state.selectedTentSize ||
|
||||||
@@ -341,6 +350,7 @@ class GrowTentKonfigurator extends Component {
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Filter products by matching tent size in "passend für Zelt" attribute
|
// Filter products by matching tent size in "passend für Zelt" attribute
|
||||||
|
// Include all size-matching products, but mark availability status
|
||||||
const matchingProducts = products.filter(product => {
|
const matchingProducts = products.filter(product => {
|
||||||
const attrs = attributesByProduct[product.id];
|
const attrs = attributesByProduct[product.id];
|
||||||
if (!attrs) return false;
|
if (!attrs) return false;
|
||||||
@@ -349,18 +359,22 @@ class GrowTentKonfigurator extends Component {
|
|||||||
const tentSizeAttr = attrs['passend für Zelt'];
|
const tentSizeAttr = attrs['passend für Zelt'];
|
||||||
if (!tentSizeAttr) return false;
|
if (!tentSizeAttr) return false;
|
||||||
|
|
||||||
// Check if tent size matches
|
// Only filter by tent size match, not by availability
|
||||||
const sizeMatch = tentSizeAttr === tentShape;
|
const sizeMatch = tentSizeAttr === tentShape;
|
||||||
|
|
||||||
// Check availability - only show products that are available for delivery
|
console.log(`Ventilation Product ${product.id}: tentSize=${tentSizeAttr}, match=${sizeMatch}`);
|
||||||
|
|
||||||
|
return sizeMatch;
|
||||||
|
}).map(product => {
|
||||||
|
// Add availability flag to each product for UI rendering
|
||||||
const isAvailable = (product.available > 0) || (product.availableSupplier === 1);
|
const isAvailable = (product.available > 0) || (product.availableSupplier === 1);
|
||||||
|
return {
|
||||||
console.log(`Ventilation Product ${product.id}: tentSize=${tentSizeAttr}, match=${sizeMatch}, available=${isAvailable}`);
|
...product,
|
||||||
|
isDeliverable: isAvailable
|
||||||
return sizeMatch && isAvailable;
|
};
|
||||||
});
|
});
|
||||||
|
|
||||||
console.log('Filtered ventilation:', matchingProducts.length);
|
console.log('Filtered ventilation (including non-deliverable):', matchingProducts.length);
|
||||||
return matchingProducts;
|
return matchingProducts;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -477,7 +491,7 @@ class GrowTentKonfigurator extends Component {
|
|||||||
if (selectedVentilationType) {
|
if (selectedVentilationType) {
|
||||||
const availableVentilation = this.getVentilationForTentShape(this.state.selectedTentShape);
|
const availableVentilation = this.getVentilationForTentShape(this.state.selectedTentShape);
|
||||||
const ventilation = availableVentilation.find(v => v.id === selectedVentilationType);
|
const ventilation = availableVentilation.find(v => v.id === selectedVentilationType);
|
||||||
if (ventilation && ventilation.price) {
|
if (ventilation && ventilation.price && ventilation.isDeliverable) {
|
||||||
total += ventilation.price;
|
total += ventilation.price;
|
||||||
itemCount++;
|
itemCount++;
|
||||||
}
|
}
|
||||||
@@ -550,7 +564,7 @@ class GrowTentKonfigurator extends Component {
|
|||||||
if (selectedVentilationType) {
|
if (selectedVentilationType) {
|
||||||
const availableVentilation = this.getVentilationForTentShape(this.state.selectedTentShape);
|
const availableVentilation = this.getVentilationForTentShape(this.state.selectedTentShape);
|
||||||
const ventilation = availableVentilation.find(v => v.id === selectedVentilationType);
|
const ventilation = availableVentilation.find(v => v.id === selectedVentilationType);
|
||||||
if (ventilation && ventilation.price) {
|
if (ventilation && ventilation.price && ventilation.isDeliverable) {
|
||||||
originalTotal += ventilation.price;
|
originalTotal += ventilation.price;
|
||||||
itemCount++;
|
itemCount++;
|
||||||
}
|
}
|
||||||
@@ -915,18 +929,53 @@ class GrowTentKonfigurator extends Component {
|
|||||||
flexDirection: 'column',
|
flexDirection: 'column',
|
||||||
borderRadius: '8px',
|
borderRadius: '8px',
|
||||||
overflow: 'hidden',
|
overflow: 'hidden',
|
||||||
cursor: 'pointer',
|
cursor: ventilation.isDeliverable ? 'pointer' : 'not-allowed',
|
||||||
border: '2px solid',
|
border: '2px solid',
|
||||||
borderColor: selectedVentilationType === ventilation.id ? '#2e7d32' : '#e0e0e0',
|
borderColor: selectedVentilationType === ventilation.id ? '#2e7d32' : '#e0e0e0',
|
||||||
backgroundColor: selectedVentilationType === ventilation.id ? '#f1f8e9' : '#ffffff',
|
backgroundColor: selectedVentilationType === ventilation.id ? '#f1f8e9' : '#ffffff',
|
||||||
'&:hover': {
|
opacity: ventilation.isDeliverable ? 1 : 0.5,
|
||||||
|
filter: ventilation.isDeliverable ? 'none' : 'grayscale(50%)',
|
||||||
|
'&:hover': ventilation.isDeliverable ? {
|
||||||
boxShadow: 6,
|
boxShadow: 6,
|
||||||
borderColor: '#2e7d32'
|
borderColor: '#2e7d32'
|
||||||
},
|
} : {},
|
||||||
transition: 'all 0.3s ease'
|
transition: 'all 0.3s ease',
|
||||||
|
position: 'relative'
|
||||||
|
}}
|
||||||
|
onClick={() => {
|
||||||
|
if (ventilation.isDeliverable) {
|
||||||
|
this.handleVentilationSelect(ventilation.id);
|
||||||
|
}
|
||||||
}}
|
}}
|
||||||
onClick={() => this.handleVentilationSelect(ventilation.id)}
|
|
||||||
>
|
>
|
||||||
|
{/* Non-deliverable overlay */}
|
||||||
|
{!ventilation.isDeliverable && (
|
||||||
|
<Box sx={{
|
||||||
|
position: 'absolute',
|
||||||
|
top: 0,
|
||||||
|
left: 0,
|
||||||
|
right: 0,
|
||||||
|
bottom: 0,
|
||||||
|
display: 'flex',
|
||||||
|
alignItems: 'center',
|
||||||
|
justifyContent: 'center',
|
||||||
|
backgroundColor: 'rgba(255, 255, 255, 0.8)',
|
||||||
|
zIndex: 1,
|
||||||
|
flexDirection: 'column'
|
||||||
|
}}>
|
||||||
|
<Typography variant="h6" sx={{
|
||||||
|
color: '#d32f2f',
|
||||||
|
fontWeight: 'bold',
|
||||||
|
textAlign: 'center',
|
||||||
|
backgroundColor: 'rgba(255, 255, 255, 0.9)',
|
||||||
|
p: 1,
|
||||||
|
borderRadius: 1
|
||||||
|
}}>
|
||||||
|
Nicht lieferbar
|
||||||
|
</Typography>
|
||||||
|
</Box>
|
||||||
|
)}
|
||||||
|
|
||||||
{/* Image */}
|
{/* Image */}
|
||||||
<Box sx={{ height: 200, display: 'flex', alignItems: 'center', justifyContent: 'center', overflow: 'hidden' }}>
|
<Box sx={{ height: 200, display: 'flex', alignItems: 'center', justifyContent: 'center', overflow: 'hidden' }}>
|
||||||
{this.renderTentImage(ventilation)}
|
{this.renderTentImage(ventilation)}
|
||||||
@@ -935,13 +984,16 @@ class GrowTentKonfigurator extends Component {
|
|||||||
{/* Content */}
|
{/* Content */}
|
||||||
<Box sx={{ p: 2, flexGrow: 1, display: 'flex', flexDirection: 'column' }}>
|
<Box sx={{ p: 2, flexGrow: 1, display: 'flex', flexDirection: 'column' }}>
|
||||||
{/* Name */}
|
{/* Name */}
|
||||||
<Typography variant="h6" gutterBottom sx={{ fontWeight: 'bold' }}>
|
<Typography variant="h6" gutterBottom sx={{
|
||||||
|
fontWeight: 'bold',
|
||||||
|
color: ventilation.isDeliverable ? 'inherit' : '#999'
|
||||||
|
}}>
|
||||||
{ventilation.name}
|
{ventilation.name}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
{/* Price with VAT */}
|
{/* Price with VAT */}
|
||||||
<Typography variant="h6" sx={{
|
<Typography variant="h6" sx={{
|
||||||
color: '#2e7d32',
|
color: ventilation.isDeliverable ? '#2e7d32' : '#999',
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
mt: 2,
|
mt: 2,
|
||||||
display: 'flex',
|
display: 'flex',
|
||||||
@@ -954,14 +1006,14 @@ class GrowTentKonfigurator extends Component {
|
|||||||
currency: 'EUR'
|
currency: 'EUR'
|
||||||
}).format(ventilation.price) : 'Kein Preis'}</span>
|
}).format(ventilation.price) : 'Kein Preis'}</span>
|
||||||
{ventilation.vat && (
|
{ventilation.vat && (
|
||||||
<small style={{ color: '#77aa77', fontSize: '0.6em' }}>
|
<small style={{ color: ventilation.isDeliverable ? '#77aa77' : '#999', fontSize: '0.6em' }}>
|
||||||
(incl. {ventilation.vat}% MwSt.,*)
|
(incl. {ventilation.vat}% MwSt.,*)
|
||||||
</small>
|
</small>
|
||||||
)}
|
)}
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
{/* Selection Indicator */}
|
{/* Selection Indicator */}
|
||||||
{selectedVentilationType === ventilation.id && (
|
{selectedVentilationType === ventilation.id && ventilation.isDeliverable && (
|
||||||
<Typography variant="body2" sx={{
|
<Typography variant="body2" sx={{
|
||||||
color: '#2e7d32',
|
color: '#2e7d32',
|
||||||
fontWeight: 'bold',
|
fontWeight: 'bold',
|
||||||
@@ -1009,7 +1061,7 @@ class GrowTentKonfigurator extends Component {
|
|||||||
const availableLamps = this.state.selectedTentShape ? this.getLampsForTentShape(this.state.selectedTentShape) : [];
|
const availableLamps = this.state.selectedTentShape ? this.getLampsForTentShape(this.state.selectedTentShape) : [];
|
||||||
const selectedLight = availableLamps.find(l => l.id === selectedLightType);
|
const selectedLight = availableLamps.find(l => l.id === selectedLightType);
|
||||||
const availableVentilation = this.state.selectedTentShape ? this.getVentilationForTentShape(this.state.selectedTentShape) : [];
|
const availableVentilation = this.state.selectedTentShape ? this.getVentilationForTentShape(this.state.selectedTentShape) : [];
|
||||||
const selectedVentilation = availableVentilation.find(v => v.id === selectedVentilationType);
|
const selectedVentilation = availableVentilation.find(v => v.id === selectedVentilationType && v.isDeliverable);
|
||||||
const selectedExtrasItems = extras.filter(e => selectedExtras.includes(e.id));
|
const selectedExtrasItems = extras.filter(e => selectedExtras.includes(e.id));
|
||||||
const savingsInfo = this.calculateSavings();
|
const savingsInfo = this.calculateSavings();
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user