From 61faf654bc792a7107b8ad77985ed2e424f9cab8 Mon Sep 17 00:00:00 2001 From: sebseb7 Date: Wed, 23 Jul 2025 08:21:30 +0200 Subject: [PATCH] refactor: standardize socket communication by replacing socket prop usage with window.socketManager across multiple components for improved consistency and maintainability --- .../profile/OrderProcessingService.js | 54 +++++-------------- src/components/profile/OrdersTab.js | 16 +++--- src/components/profile/SettingsTab.js | 8 +-- src/pages/AdminPage.js | 32 +++-------- src/pages/GrowTentKonfigurator.js | 10 ++-- src/pages/ResetPassword.js | 4 +- src/pages/ServerLogsPage.js | 34 +++--------- src/pages/Sitemap.js | 10 ++-- src/pages/UsersPage.js | 30 ++--------- src/services/telemetryService.js | 2 +- 10 files changed, 52 insertions(+), 148 deletions(-) diff --git a/src/components/profile/OrderProcessingService.js b/src/components/profile/OrderProcessingService.js index 248cc7b..2723047 100644 --- a/src/components/profile/OrderProcessingService.js +++ b/src/components/profile/OrderProcessingService.js @@ -145,26 +145,24 @@ class OrderProcessingService { } // If socket is ready, process immediately - const context = this.getContext(); - if (context && context.socket && context.socket.connected) { + const { isLoggedIn: isAuthenticated } = isUserLoggedIn(); if (isAuthenticated) { this.sendStripeOrder(); return; } - } + // Wait for socket to be ready this.socketHandler = () => { - const context = this.getContext(); - if (context && context.socket && context.socket.connected) { + const { isLoggedIn: isAuthenticated } = isUserLoggedIn(); const state = this.getState(); if (isAuthenticated && state.showPaymentConfirmation && !state.isCompletingOrder) { this.sendStripeOrder(); } - } + // Clean up if (this.socketHandler) { window.removeEventListener('cart', this.socketHandler); @@ -213,9 +211,8 @@ class OrderProcessingService { saveAddressForFuture, }; - // Emit stripe order to backend via socket.io - const context = this.getContext(); - context.socket.emit("issueStripeOrder", orderData, (response) => { + + window.socketManager.emit("issueStripeOrder", orderData, (response) => { if (response.success) { this.setState({ isCompletingOrder: false, @@ -247,9 +244,8 @@ class OrderProcessingService { // Process regular (non-Stripe) orders processRegularOrder(orderData) { - const context = this.getContext(); - if (context && context.socket && context.socket.connected) { - context.socket.emit("issueOrder", orderData, (response) => { + + window.socketManager.emit("issueOrder", orderData, (response) => { if (response.success) { // Clear the cart window.cart = []; @@ -274,20 +270,12 @@ class OrderProcessingService { }); } }); - } else { - console.error("Socket context not available"); - this.setState({ - isCompletingOrder: false, - completionError: "Cannot connect to server. Please try again later.", - }); - } } // Create Stripe payment intent createStripeIntent(totalAmount, loadStripeComponent) { - const context = this.getContext(); - if (context && context.socket && context.socket.connected) { - context.socket.emit( + + window.socketManager.emit( "createStripeIntent", { amount: totalAmount }, (response) => { @@ -302,20 +290,13 @@ class OrderProcessingService { } } ); - } else { - console.error("Socket context not available"); - this.setState({ - isCompletingOrder: false, - completionError: "Cannot connect to server. Please try again later.", - }); - } - } + }; + + // Create Mollie payment intent createMollieIntent(mollieOrderData) { - const context = this.getContext(); - if (context && context.socket && context.socket.connected) { - context.socket.emit( + window.socketManager.emit( "createMollieIntent", mollieOrderData, (response) => { @@ -336,13 +317,6 @@ class OrderProcessingService { } } ); - } else { - console.error("Socket context not available"); - this.setState({ - isCompletingOrder: false, - completionError: "Cannot connect to server. Please try again later.", - }); - } } // Calculate delivery cost diff --git a/src/components/profile/OrdersTab.js b/src/components/profile/OrdersTab.js index 850802f..beaf88f 100644 --- a/src/components/profile/OrdersTab.js +++ b/src/components/profile/OrdersTab.js @@ -98,10 +98,10 @@ const OrdersTab = ({ orderIdFromHash, t }) => { ); const fetchOrders = useCallback(() => { - if (socket && socket.connected) { + setLoading(true); setError(null); - socket.emit("getOrders", (response) => { + window.socketManager.emit("getOrders", (response) => { if (response.success) { setOrders(response.orders); } else { @@ -109,12 +109,8 @@ const OrdersTab = ({ orderIdFromHash, t }) => { } setLoading(false); }); - } else { - // Socket not connected yet, but don't show error immediately on first load - console.log("Socket not connected yet, waiting for connection to fetch orders"); - setLoading(false); // Stop loading when socket is not connected - } - }, [socket]); + + }, []); useEffect(() => { fetchOrders(); @@ -166,10 +162,10 @@ const OrdersTab = ({ orderIdFromHash, t }) => { // Handle cancel confirmation const handleConfirmCancel = () => { - if (!orderToCancel || !socket) return; + if (!orderToCancel) return; setIsCancelling(true); - socket.emit('cancelOrder', { orderId: orderToCancel.orderId }, (response) => { + window.socketManager.emit('cancelOrder', { orderId: orderToCancel.orderId }, (response) => { setIsCancelling(false); setCancelConfirmOpen(false); diff --git a/src/components/profile/SettingsTab.js b/src/components/profile/SettingsTab.js index 86feb6e..1984afa 100644 --- a/src/components/profile/SettingsTab.js +++ b/src/components/profile/SettingsTab.js @@ -48,7 +48,7 @@ class SettingsTab extends Component { this.setState({ newEmail: user.email || '' }); // Check if user has an API key - this.props.socket.emit('isApiKey', (response) => { + window.socketManager.emit('isApiKey', (response) => { if (response.success && response.hasApiKey) { this.setState({ hasApiKey: true, @@ -90,7 +90,7 @@ class SettingsTab extends Component { this.setState({ loading: true }); // Call socket.io endpoint to update password - this.props.socket.emit('updatePassword', + window.socketManager.emit('updatePassword', { oldPassword: this.state.currentPassword, newPassword: this.state.newPassword }, (response) => { this.setState({ loading: false }); @@ -134,7 +134,7 @@ class SettingsTab extends Component { this.setState({ loading: true }); // Call socket.io endpoint to update email - this.props.socket.emit('updateEmail', + window.socketManager.emit('updateEmail', { password: this.state.password, email: this.state.newEmail }, (response) => { this.setState({ loading: false }); @@ -184,7 +184,7 @@ class SettingsTab extends Component { try { const user = JSON.parse(storedUser); - this.props.socket.emit('createApiKey', user.id, (response) => { + window.socketManager.emit('createApiKey', user.id, (response) => { this.setState({ loadingApiKey: false }); if (response.success) { diff --git a/src/pages/AdminPage.js b/src/pages/AdminPage.js index 57ead11..5b8dac9 100644 --- a/src/pages/AdminPage.js +++ b/src/pages/AdminPage.js @@ -108,21 +108,6 @@ class AdminPage extends React.Component { window.addEventListener('storage', this.handleStorageChange); } - componentDidUpdate(prevProps) { - // Handle socket connection changes - const wasConnected = prevProps.socket && prevProps.socket.connected; - const isNowConnected = this.props.socket && this.props.socket.connected; - - if (!wasConnected && isNowConnected) { - // Socket just connected, add listeners and reload data - this.addSocketListeners(); - this.loadInitialData(); - } else if (wasConnected && !isNowConnected) { - // Socket just disconnected, remove listeners - this.removeSocketListeners(); - } - } - componentWillUnmount() { this.removeSocketListeners(); // Clear interval and remove event listeners @@ -133,12 +118,11 @@ class AdminPage extends React.Component { } loadInitialData = () => { - if (this.props.socket && this.props.socket.connected) { - this.props.socket.emit('getStats', (stats) => { + window.socketManager.emit('getStats', (stats) => { console.log('AdminPage: getStats', JSON.stringify(stats,null,2)); this.setState({stats: stats}); }); - this.props.socket.emit('initialCarts', (carts) => { + window.socketManager.emit('initialCarts', (carts) => { console.log('AdminPage: initialCarts', carts); if(carts && carts.success == true) { @@ -153,21 +137,19 @@ class AdminPage extends React.Component { this.setState({ users: users }); } }); - } } addSocketListeners = () => { - if (this.props.socket && this.props.socket.connected) { // Remove existing listeners first to avoid duplicates this.removeSocketListeners(); - this.props.socket.on('cartUpdated', this.handleCartUpdated); - } + window.socketManager.on('cartUpdated', this.handleCartUpdated); + } removeSocketListeners = () => { - if (this.props.socket) { - this.props.socket.off('cartUpdated', this.handleCartUpdated); - } + + window.socketManager.off('cartUpdated', this.handleCartUpdated); + } formatPrice = (price) => { diff --git a/src/pages/GrowTentKonfigurator.js b/src/pages/GrowTentKonfigurator.js index efad6e7..46cec1d 100644 --- a/src/pages/GrowTentKonfigurator.js +++ b/src/pages/GrowTentKonfigurator.js @@ -143,19 +143,15 @@ class GrowTentKonfigurator extends Component { return; } - //if (!this.props.socket || !this.props.socket.connected) { - // console.log("Socket not connected yet, waiting for connection to fetch category data"); - // return; - //} console.log(`productList:${categoryId}`); - this.props.socket.off(`productList:${categoryId}`); + window.socketManager.off(`productList:${categoryId}`); - this.props.socket.on(`productList:${categoryId}`,(response) => { + window.socketManager.on(`productList:${categoryId}`,(response) => { console.log("getCategoryProducts full response", response); setCachedCategoryData(categoryId, response); }); - this.props.socket.emit("getCategoryProducts", { categoryId: categoryId }, + window.socketManager.emit("getCategoryProducts", { categoryId: categoryId }, (response) => { console.log("getCategoryProducts stub response", response); } diff --git a/src/pages/ResetPassword.js b/src/pages/ResetPassword.js index 6787d95..4023589 100644 --- a/src/pages/ResetPassword.js +++ b/src/pages/ResetPassword.js @@ -13,7 +13,7 @@ import { } from '@mui/material'; import LockResetIcon from '@mui/icons-material/LockReset'; -const ResetPassword = ({ socket }) => { +const ResetPassword = () => { const navigate = useNavigate(); const location = useLocation(); const { t } = useTranslation(); @@ -59,7 +59,7 @@ const ResetPassword = ({ socket }) => { setError(''); // Emit verifyResetToken event - socket.emit('verifyResetToken', { + window.socketManager.emit('verifyResetToken', { token: token, newPassword: newPassword }, (response) => { diff --git a/src/pages/ServerLogsPage.js b/src/pages/ServerLogsPage.js index 96ce1af..03574d2 100644 --- a/src/pages/ServerLogsPage.js +++ b/src/pages/ServerLogsPage.js @@ -104,8 +104,8 @@ class ServerLogsPage extends React.Component { } loadHistoricalLogs = () => { - if (this.props.socket && this.props.socket.connected) { - this.props.socket.emit('getLog', (response) => { + + window.socketManager.emit('getLog', (response) => { if (response.success) { console.log('Last 50 historical logs:', response.data.lines); const historicalLogs = (response.data.lines || []) @@ -121,7 +121,6 @@ class ServerLogsPage extends React.Component { this.setState({ historicalLogsLoaded: true }); // Mark as attempted even if failed } }); - } } componentDidMount() { @@ -134,23 +133,6 @@ class ServerLogsPage extends React.Component { window.addEventListener('storage', this.handleStorageChange); } - componentDidUpdate(prevProps) { - // Handle socket connection changes - const wasConnected = prevProps.socket && prevProps.socket.connected; - const isNowConnected = this.props.socket && this.props.socket.connected; - - if (!wasConnected && isNowConnected) { - // Socket just connected, add listeners and reload data - this.addSocketListeners(); - if (!this.state.historicalLogsLoaded) { - this.loadHistoricalLogs(); - } - } else if (wasConnected && !isNowConnected) { - // Socket just disconnected, remove listeners - this.removeSocketListeners(); - } - } - componentWillUnmount() { this.removeSocketListeners(); // Clear interval and remove event listeners @@ -161,17 +143,13 @@ class ServerLogsPage extends React.Component { } addSocketListeners = () => { - if (this.props.socket && this.props.socket.connected) { - // Remove existing listeners first to avoid duplicates - this.removeSocketListeners(); - this.props.socket.on('log', this.handleLogEntry); - } + // Remove existing listeners first to avoid duplicates + this.removeSocketListeners(); + window.socketManager.on('log', this.handleLogEntry); } removeSocketListeners = () => { - if (this.props.socket) { - this.props.socket.off('log', this.handleLogEntry); - } + window.socketManager.off('log', this.handleLogEntry); } formatLogLevel = (level) => { diff --git a/src/pages/Sitemap.js b/src/pages/Sitemap.js index 82bc916..613db7a 100644 --- a/src/pages/Sitemap.js +++ b/src/pages/Sitemap.js @@ -1,4 +1,4 @@ -import React, { useState, useEffect, useContext } from 'react'; +import React, { useState, useEffect } from 'react'; import Typography from '@mui/material/Typography'; import List from '@mui/material/List'; import ListItem from '@mui/material/ListItem'; @@ -7,7 +7,6 @@ import Box from '@mui/material/Box'; import CircularProgress from '@mui/material/CircularProgress'; import { Link as RouterLink } from 'react-router-dom'; import LegalPage from './LegalPage.js'; -import SocketContext from '../contexts/SocketContext.js'; // Helper function to recursively collect all categories from the tree const collectAllCategories = (categoryNode, categories = [], level = 0) => { @@ -68,7 +67,6 @@ const Sitemap = () => { const initialCategories = initializeCategories(); const [categories, setCategories] = useState(initialCategories); const [loading, setLoading] = useState(initialCategories.length === 0); - const context = useContext(SocketContext); const sitemapLinks = [ @@ -105,8 +103,8 @@ const Sitemap = () => { } // Otherwise, fetch from socket if available (only in browser) - if (context && context.socket && context.socket.connected && typeof window !== "undefined") { - context.socket.emit('categoryList', { categoryId: 209, language: 'en', requestTranslation: true }, (response) => { + if (typeof window !== "undefined") { + window.socketManager.emit('categoryList', { categoryId: 209, language: 'en', requestTranslation: true }, (response) => { if (response && response.categoryTree) { // Store in cache try { @@ -133,7 +131,7 @@ const Sitemap = () => { }; fetchCategories(); - }, [context, categories.length]); + }, [categories.length]); const content = ( <> diff --git a/src/pages/UsersPage.js b/src/pages/UsersPage.js index 38845fe..dceef7d 100644 --- a/src/pages/UsersPage.js +++ b/src/pages/UsersPage.js @@ -91,17 +91,6 @@ class UsersPage extends React.Component { window.addEventListener('storage', this.handleStorageChange); } - componentDidUpdate(prevProps) { - // Handle socket connection changes - const wasConnected = prevProps.socket && prevProps.socket.connected; - const isNowConnected = this.props.socket && this.props.socket.connected; - - if (!wasConnected && isNowConnected) { - // Socket just connected, reload data - this.loadInitialData(); - } - } - componentWillUnmount() { // Clear interval and remove event listeners if (this.checkLoginInterval) { @@ -111,8 +100,8 @@ class UsersPage extends React.Component { } loadInitialData = () => { - if (this.props.socket && this.props.socket.connected) { - this.props.socket.emit('getUsers', (response) => { + + window.socketManager.emit('getUsers', (response) => { if (response.success) { console.log('Users:', response.data.users); console.log('Total count:', response.data.totalCount); @@ -126,7 +115,7 @@ class UsersPage extends React.Component { console.error('Error:', response.error); } }); - } + } formatDate = (dateString) => { @@ -190,14 +179,9 @@ class UsersPage extends React.Component { } handleSwitchUser = (email) => { - if (!this.props.socket || !this.props.socket.connected) { - this.showNotification('Socket not connected', 'error'); - return; - } - this.setState({ switchingUser: true }); - this.props.socket.emit('switchUser', { email }, (response) => { + window.socketManager.emit('switchUser', { email }, (response) => { console.log('Switch user response:', response); this.setState({ switchingUser: false }); @@ -225,14 +209,10 @@ class UsersPage extends React.Component { } handleSwitchBackToAdmin = () => { - if (!this.props.socket || !this.props.socket.connected) { - this.showNotification('Socket not connected', 'error'); - return; - } this.setState({ switchingUser: true }); - this.props.socket.emit('switchBackToAdmin', (response) => { + window.socketManager.emit('switchBackToAdmin', (response) => { console.log('Switch back to admin response:', response); this.setState({ switchingUser: false }); diff --git a/src/services/telemetryService.js b/src/services/telemetryService.js index de2b8b6..3b6e2bb 100644 --- a/src/services/telemetryService.js +++ b/src/services/telemetryService.js @@ -88,7 +88,7 @@ class TelemetryService { } try { - this.socket.emit('telemetry', { + window.socketManager.emit('telemetry', { type: 'consoleLog', level: level, message: message,