From 0dd1e01018d71a1647bfa88aa2a98855203c2ca0 Mon Sep 17 00:00:00 2001 From: sebseb7 Date: Tue, 9 Sep 2025 18:10:08 +0200 Subject: [PATCH] feat(GrowTentKonfigurator): add periodic cache validity checking Implement interval-based cache monitoring every 60 seconds to detect misses or expirations across categories (Zelte, Lampen, Abluft-sets, Set-zubehoer). Update per-category load status tracking to conditionally render sections independently, improving UX by avoiding global loading delays and ensuring timely refetches. Clear interval on unmount to prevent memory leaks. --- src/pages/GrowTentKonfigurator.js | 127 ++++++++++++++++-------------- 1 file changed, 68 insertions(+), 59 deletions(-) diff --git a/src/pages/GrowTentKonfigurator.js b/src/pages/GrowTentKonfigurator.js index 9c41c1f..cf153d6 100644 --- a/src/pages/GrowTentKonfigurator.js +++ b/src/pages/GrowTentKonfigurator.js @@ -92,8 +92,7 @@ class GrowTentKonfigurator extends Component { this.handleExtraToggle = this.handleExtraToggle.bind(this); this.calculateTotalPrice = this.calculateTotalPrice.bind(this); this.saveStateToWindow = this.saveStateToWindow.bind(this); - - + this.checkCacheValidity = this.checkCacheValidity.bind(this); } saveStateToWindow() { @@ -116,6 +115,7 @@ class GrowTentKonfigurator extends Component { this.fetchCategoryData("Lampen"); this.fetchCategoryData("Abluft-sets"); this.fetchCategoryData("Set-zubehoer"); + this.cacheCheckInterval = setInterval(this.checkCacheValidity, 60000); } componentDidUpdate(prevProps, prevState) { @@ -156,12 +156,25 @@ class GrowTentKonfigurator extends Component { } } + componentWillUnmount() { + if (this.cacheCheckInterval) { + clearInterval(this.cacheCheckInterval); + } + } fetchCategoryData(categoryId) { const cachedData = getCachedCategoryData(categoryId); if (cachedData) { + this.setState(prevState => ({ + categoryLoadStatus: { + ...prevState.categoryLoadStatus, + [categoryId]: true + } + })); return; } + console.log(`Cache miss for category ${categoryId}, fetching...`); + window.socketManager.off(`productList:${categoryId}`); window.socketManager.on(`productList:${categoryId}`,(response) => { @@ -182,6 +195,23 @@ class GrowTentKonfigurator extends Component { ); } + checkCacheValidity() { + const categories = ["Zelte", "Lampen", "Abluft-sets", "Set-zubehoer"]; + let needsUpdate = false; + const newStatus = { ...this.state.categoryLoadStatus }; + for (const categoryId of categories) { + if (newStatus[categoryId] && !getCachedCategoryData(categoryId)) { + console.log(`Refetching ${categoryId} due to cache miss/expiry`); + newStatus[categoryId] = false; + needsUpdate = true; + this.fetchCategoryData(categoryId); + } + } + if (needsUpdate) { + this.setState({ categoryLoadStatus: newStatus }); + } + } + handleTentShapeSelect(shapeId) { this.setState({ selectedTentShape: shapeId }); } @@ -600,22 +630,20 @@ class GrowTentKonfigurator extends Component { return null; // Don't show tent sizes until shape is selected } + if (!this.state.categoryLoadStatus["Zelte"]) { + return ( + + + Lade Growbox-Produkte... + + + ); + } + // Get real filtered tent products for the selected shape const filteredTents = this.getTentsForShape(selectedTentShape); - // Show loading state if data is not yet available if (filteredTents.length === 0) { - const cachedData = getCachedCategoryData('Zelte'); - if (!cachedData) { - return ( - - - Lade Growbox-Produkte... - - - ); - } - // If we have cached data but no filtered tents, show empty state return ( @@ -624,18 +652,6 @@ class GrowTentKonfigurator extends Component { ); } - - - if (filteredTents.length === 0) { - return ( - - - Keine Produkte verfügbar - - - ); - } - return ( @@ -743,11 +759,7 @@ class GrowTentKonfigurator extends Component { ); } - // Get real lamps for selected tent shape - const availableLamps = this.getLampsForTentShape(selectedTentShape); - const cachedData = getCachedCategoryData('Lampen'); - - if (!cachedData) { + if (!this.state.categoryLoadStatus["Lampen"]) { return ( @@ -760,6 +772,8 @@ class GrowTentKonfigurator extends Component { ); } + const availableLamps = this.getLampsForTentShape(selectedTentShape); + if (availableLamps.length === 0) { return ( @@ -772,7 +786,7 @@ class GrowTentKonfigurator extends Component { ); } - + return ( @@ -872,11 +886,7 @@ class GrowTentKonfigurator extends Component { ); } - // Get real ventilation products for selected tent shape - const availableVentilation = this.getVentilationForTentShape(selectedTentShape); - const cachedData = getCachedCategoryData('Abluft-sets'); - - if (!cachedData) { + if (!this.state.categoryLoadStatus["Abluft-sets"]) { return ( @@ -889,6 +899,8 @@ class GrowTentKonfigurator extends Component { ); } + const availableVentilation = this.getVentilationForTentShape(selectedTentShape); + if (availableVentilation.length === 0) { return ( @@ -901,7 +913,7 @@ class GrowTentKonfigurator extends Component { ); } - + return ( @@ -1025,6 +1037,19 @@ class GrowTentKonfigurator extends Component { renderExtrasSection() { const { selectedExtras } = this.state; + if (!this.state.categoryLoadStatus["Set-zubehoer"]) { + return ( + + + 5. Extras hinzufügen (optional) + + + Lade Extras... + + + ); + } + const extrasData = getCachedCategoryData('Set-zubehoer'); if (!extrasData) { @@ -1034,7 +1059,7 @@ class GrowTentKonfigurator extends Component { 5. Extras hinzufügen (optional) - Lade Extras... + Keine Extras verfügbar ); @@ -1225,14 +1250,6 @@ class GrowTentKonfigurator extends Component { render() { - // Check if all 4 category data sections have loaded - const tentsData = getCachedCategoryData('Zelte'); - const lampsData = getCachedCategoryData('Lampen'); - const ventilationData = getCachedCategoryData('Abluft-sets'); - const extrasData = getCachedCategoryData('Set-zubehoer'); - - const allDataLoaded = tentsData && lampsData && ventilationData && extrasData; - return ( @@ -1297,27 +1314,19 @@ class GrowTentKonfigurator extends Component { {this.renderTentShapeSection()} - - {allDataLoaded && ( - <> - - {this.renderTentSizeSection()} {this.state.selectedTentShape && } - + {this.renderLightSection()} - + {this.renderVentilationSection()} - + {this.renderExtrasSection()} - + {/* Inline summary section - expands when scrolling to bottom */} {this.renderInlineSummary()} - - )} - );