refactor: standardize socket communication by replacing socket prop usage with window.socketManager across multiple components for improved consistency and maintainability

This commit is contained in:
sebseb7
2025-07-23 08:21:30 +02:00
parent 4e6b63a6a4
commit 61faf654bc
10 changed files with 52 additions and 148 deletions

View File

@@ -145,26 +145,24 @@ class OrderProcessingService {
} }
// If socket is ready, process immediately // If socket is ready, process immediately
const context = this.getContext();
if (context && context.socket && context.socket.connected) {
const { isLoggedIn: isAuthenticated } = isUserLoggedIn(); const { isLoggedIn: isAuthenticated } = isUserLoggedIn();
if (isAuthenticated) { if (isAuthenticated) {
this.sendStripeOrder(); this.sendStripeOrder();
return; return;
} }
}
// Wait for socket to be ready // Wait for socket to be ready
this.socketHandler = () => { this.socketHandler = () => {
const context = this.getContext();
if (context && context.socket && context.socket.connected) {
const { isLoggedIn: isAuthenticated } = isUserLoggedIn(); const { isLoggedIn: isAuthenticated } = isUserLoggedIn();
const state = this.getState(); const state = this.getState();
if (isAuthenticated && state.showPaymentConfirmation && !state.isCompletingOrder) { if (isAuthenticated && state.showPaymentConfirmation && !state.isCompletingOrder) {
this.sendStripeOrder(); this.sendStripeOrder();
} }
}
// Clean up // Clean up
if (this.socketHandler) { if (this.socketHandler) {
window.removeEventListener('cart', this.socketHandler); window.removeEventListener('cart', this.socketHandler);
@@ -213,9 +211,8 @@ class OrderProcessingService {
saveAddressForFuture, saveAddressForFuture,
}; };
// Emit stripe order to backend via socket.io
const context = this.getContext(); window.socketManager.emit("issueStripeOrder", orderData, (response) => {
context.socket.emit("issueStripeOrder", orderData, (response) => {
if (response.success) { if (response.success) {
this.setState({ this.setState({
isCompletingOrder: false, isCompletingOrder: false,
@@ -247,9 +244,8 @@ class OrderProcessingService {
// Process regular (non-Stripe) orders // Process regular (non-Stripe) orders
processRegularOrder(orderData) { processRegularOrder(orderData) {
const context = this.getContext();
if (context && context.socket && context.socket.connected) { window.socketManager.emit("issueOrder", orderData, (response) => {
context.socket.emit("issueOrder", orderData, (response) => {
if (response.success) { if (response.success) {
// Clear the cart // Clear the cart
window.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 // Create Stripe payment intent
createStripeIntent(totalAmount, loadStripeComponent) { createStripeIntent(totalAmount, loadStripeComponent) {
const context = this.getContext();
if (context && context.socket && context.socket.connected) { window.socketManager.emit(
context.socket.emit(
"createStripeIntent", "createStripeIntent",
{ amount: totalAmount }, { amount: totalAmount },
(response) => { (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 // Create Mollie payment intent
createMollieIntent(mollieOrderData) { createMollieIntent(mollieOrderData) {
const context = this.getContext(); window.socketManager.emit(
if (context && context.socket && context.socket.connected) {
context.socket.emit(
"createMollieIntent", "createMollieIntent",
mollieOrderData, mollieOrderData,
(response) => { (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 // Calculate delivery cost

View File

@@ -98,10 +98,10 @@ const OrdersTab = ({ orderIdFromHash, t }) => {
); );
const fetchOrders = useCallback(() => { const fetchOrders = useCallback(() => {
if (socket && socket.connected) {
setLoading(true); setLoading(true);
setError(null); setError(null);
socket.emit("getOrders", (response) => { window.socketManager.emit("getOrders", (response) => {
if (response.success) { if (response.success) {
setOrders(response.orders); setOrders(response.orders);
} else { } else {
@@ -109,12 +109,8 @@ const OrdersTab = ({ orderIdFromHash, t }) => {
} }
setLoading(false); 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(() => { useEffect(() => {
fetchOrders(); fetchOrders();
@@ -166,10 +162,10 @@ const OrdersTab = ({ orderIdFromHash, t }) => {
// Handle cancel confirmation // Handle cancel confirmation
const handleConfirmCancel = () => { const handleConfirmCancel = () => {
if (!orderToCancel || !socket) return; if (!orderToCancel) return;
setIsCancelling(true); setIsCancelling(true);
socket.emit('cancelOrder', { orderId: orderToCancel.orderId }, (response) => { window.socketManager.emit('cancelOrder', { orderId: orderToCancel.orderId }, (response) => {
setIsCancelling(false); setIsCancelling(false);
setCancelConfirmOpen(false); setCancelConfirmOpen(false);

View File

@@ -48,7 +48,7 @@ class SettingsTab extends Component {
this.setState({ newEmail: user.email || '' }); this.setState({ newEmail: user.email || '' });
// Check if user has an API key // Check if user has an API key
this.props.socket.emit('isApiKey', (response) => { window.socketManager.emit('isApiKey', (response) => {
if (response.success && response.hasApiKey) { if (response.success && response.hasApiKey) {
this.setState({ this.setState({
hasApiKey: true, hasApiKey: true,
@@ -90,7 +90,7 @@ class SettingsTab extends Component {
this.setState({ loading: true }); this.setState({ loading: true });
// Call socket.io endpoint to update password // Call socket.io endpoint to update password
this.props.socket.emit('updatePassword', window.socketManager.emit('updatePassword',
{ oldPassword: this.state.currentPassword, newPassword: this.state.newPassword }, { oldPassword: this.state.currentPassword, newPassword: this.state.newPassword },
(response) => { (response) => {
this.setState({ loading: false }); this.setState({ loading: false });
@@ -134,7 +134,7 @@ class SettingsTab extends Component {
this.setState({ loading: true }); this.setState({ loading: true });
// Call socket.io endpoint to update email // Call socket.io endpoint to update email
this.props.socket.emit('updateEmail', window.socketManager.emit('updateEmail',
{ password: this.state.password, email: this.state.newEmail }, { password: this.state.password, email: this.state.newEmail },
(response) => { (response) => {
this.setState({ loading: false }); this.setState({ loading: false });
@@ -184,7 +184,7 @@ class SettingsTab extends Component {
try { try {
const user = JSON.parse(storedUser); const user = JSON.parse(storedUser);
this.props.socket.emit('createApiKey', user.id, (response) => { window.socketManager.emit('createApiKey', user.id, (response) => {
this.setState({ loadingApiKey: false }); this.setState({ loadingApiKey: false });
if (response.success) { if (response.success) {

View File

@@ -108,21 +108,6 @@ class AdminPage extends React.Component {
window.addEventListener('storage', this.handleStorageChange); 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() { componentWillUnmount() {
this.removeSocketListeners(); this.removeSocketListeners();
// Clear interval and remove event listeners // Clear interval and remove event listeners
@@ -133,12 +118,11 @@ class AdminPage extends React.Component {
} }
loadInitialData = () => { loadInitialData = () => {
if (this.props.socket && this.props.socket.connected) { window.socketManager.emit('getStats', (stats) => {
this.props.socket.emit('getStats', (stats) => {
console.log('AdminPage: getStats', JSON.stringify(stats,null,2)); console.log('AdminPage: getStats', JSON.stringify(stats,null,2));
this.setState({stats: stats}); this.setState({stats: stats});
}); });
this.props.socket.emit('initialCarts', (carts) => { window.socketManager.emit('initialCarts', (carts) => {
console.log('AdminPage: initialCarts', carts); console.log('AdminPage: initialCarts', carts);
if(carts && carts.success == true) if(carts && carts.success == true)
{ {
@@ -154,20 +138,18 @@ class AdminPage extends React.Component {
} }
}); });
} }
}
addSocketListeners = () => { addSocketListeners = () => {
if (this.props.socket && this.props.socket.connected) {
// Remove existing listeners first to avoid duplicates // Remove existing listeners first to avoid duplicates
this.removeSocketListeners(); this.removeSocketListeners();
this.props.socket.on('cartUpdated', this.handleCartUpdated); window.socketManager.on('cartUpdated', this.handleCartUpdated);
}
} }
removeSocketListeners = () => { removeSocketListeners = () => {
if (this.props.socket) {
this.props.socket.off('cartUpdated', this.handleCartUpdated); window.socketManager.off('cartUpdated', this.handleCartUpdated);
}
} }
formatPrice = (price) => { formatPrice = (price) => {

View File

@@ -143,19 +143,15 @@ class GrowTentKonfigurator extends Component {
return; 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}`); 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); console.log("getCategoryProducts full response", response);
setCachedCategoryData(categoryId, response); setCachedCategoryData(categoryId, response);
}); });
this.props.socket.emit("getCategoryProducts", { categoryId: categoryId }, window.socketManager.emit("getCategoryProducts", { categoryId: categoryId },
(response) => { (response) => {
console.log("getCategoryProducts stub response", response); console.log("getCategoryProducts stub response", response);
} }

View File

@@ -13,7 +13,7 @@ import {
} from '@mui/material'; } from '@mui/material';
import LockResetIcon from '@mui/icons-material/LockReset'; import LockResetIcon from '@mui/icons-material/LockReset';
const ResetPassword = ({ socket }) => { const ResetPassword = () => {
const navigate = useNavigate(); const navigate = useNavigate();
const location = useLocation(); const location = useLocation();
const { t } = useTranslation(); const { t } = useTranslation();
@@ -59,7 +59,7 @@ const ResetPassword = ({ socket }) => {
setError(''); setError('');
// Emit verifyResetToken event // Emit verifyResetToken event
socket.emit('verifyResetToken', { window.socketManager.emit('verifyResetToken', {
token: token, token: token,
newPassword: newPassword newPassword: newPassword
}, (response) => { }, (response) => {

View File

@@ -104,8 +104,8 @@ class ServerLogsPage extends React.Component {
} }
loadHistoricalLogs = () => { loadHistoricalLogs = () => {
if (this.props.socket && this.props.socket.connected) {
this.props.socket.emit('getLog', (response) => { window.socketManager.emit('getLog', (response) => {
if (response.success) { if (response.success) {
console.log('Last 50 historical logs:', response.data.lines); console.log('Last 50 historical logs:', response.data.lines);
const historicalLogs = (response.data.lines || []) const historicalLogs = (response.data.lines || [])
@@ -122,7 +122,6 @@ class ServerLogsPage extends React.Component {
} }
}); });
} }
}
componentDidMount() { componentDidMount() {
this.addSocketListeners(); this.addSocketListeners();
@@ -134,23 +133,6 @@ class ServerLogsPage extends React.Component {
window.addEventListener('storage', this.handleStorageChange); 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() { componentWillUnmount() {
this.removeSocketListeners(); this.removeSocketListeners();
// Clear interval and remove event listeners // Clear interval and remove event listeners
@@ -161,17 +143,13 @@ class ServerLogsPage extends React.Component {
} }
addSocketListeners = () => { addSocketListeners = () => {
if (this.props.socket && this.props.socket.connected) {
// Remove existing listeners first to avoid duplicates // Remove existing listeners first to avoid duplicates
this.removeSocketListeners(); this.removeSocketListeners();
this.props.socket.on('log', this.handleLogEntry); window.socketManager.on('log', this.handleLogEntry);
}
} }
removeSocketListeners = () => { removeSocketListeners = () => {
if (this.props.socket) { window.socketManager.off('log', this.handleLogEntry);
this.props.socket.off('log', this.handleLogEntry);
}
} }
formatLogLevel = (level) => { formatLogLevel = (level) => {

View File

@@ -1,4 +1,4 @@
import React, { useState, useEffect, useContext } from 'react'; import React, { useState, useEffect } from 'react';
import Typography from '@mui/material/Typography'; import Typography from '@mui/material/Typography';
import List from '@mui/material/List'; import List from '@mui/material/List';
import ListItem from '@mui/material/ListItem'; import ListItem from '@mui/material/ListItem';
@@ -7,7 +7,6 @@ import Box from '@mui/material/Box';
import CircularProgress from '@mui/material/CircularProgress'; import CircularProgress from '@mui/material/CircularProgress';
import { Link as RouterLink } from 'react-router-dom'; import { Link as RouterLink } from 'react-router-dom';
import LegalPage from './LegalPage.js'; import LegalPage from './LegalPage.js';
import SocketContext from '../contexts/SocketContext.js';
// Helper function to recursively collect all categories from the tree // Helper function to recursively collect all categories from the tree
const collectAllCategories = (categoryNode, categories = [], level = 0) => { const collectAllCategories = (categoryNode, categories = [], level = 0) => {
@@ -68,7 +67,6 @@ const Sitemap = () => {
const initialCategories = initializeCategories(); const initialCategories = initializeCategories();
const [categories, setCategories] = useState(initialCategories); const [categories, setCategories] = useState(initialCategories);
const [loading, setLoading] = useState(initialCategories.length === 0); const [loading, setLoading] = useState(initialCategories.length === 0);
const context = useContext(SocketContext);
const sitemapLinks = [ const sitemapLinks = [
@@ -105,8 +103,8 @@ const Sitemap = () => {
} }
// Otherwise, fetch from socket if available (only in browser) // Otherwise, fetch from socket if available (only in browser)
if (context && context.socket && context.socket.connected && typeof window !== "undefined") { if (typeof window !== "undefined") {
context.socket.emit('categoryList', { categoryId: 209, language: 'en', requestTranslation: true }, (response) => { window.socketManager.emit('categoryList', { categoryId: 209, language: 'en', requestTranslation: true }, (response) => {
if (response && response.categoryTree) { if (response && response.categoryTree) {
// Store in cache // Store in cache
try { try {
@@ -133,7 +131,7 @@ const Sitemap = () => {
}; };
fetchCategories(); fetchCategories();
}, [context, categories.length]); }, [categories.length]);
const content = ( const content = (
<> <>

View File

@@ -91,17 +91,6 @@ class UsersPage extends React.Component {
window.addEventListener('storage', this.handleStorageChange); 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() { componentWillUnmount() {
// Clear interval and remove event listeners // Clear interval and remove event listeners
if (this.checkLoginInterval) { if (this.checkLoginInterval) {
@@ -111,8 +100,8 @@ class UsersPage extends React.Component {
} }
loadInitialData = () => { loadInitialData = () => {
if (this.props.socket && this.props.socket.connected) {
this.props.socket.emit('getUsers', (response) => { window.socketManager.emit('getUsers', (response) => {
if (response.success) { if (response.success) {
console.log('Users:', response.data.users); console.log('Users:', response.data.users);
console.log('Total count:', response.data.totalCount); console.log('Total count:', response.data.totalCount);
@@ -126,7 +115,7 @@ class UsersPage extends React.Component {
console.error('Error:', response.error); console.error('Error:', response.error);
} }
}); });
}
} }
formatDate = (dateString) => { formatDate = (dateString) => {
@@ -190,14 +179,9 @@ class UsersPage extends React.Component {
} }
handleSwitchUser = (email) => { handleSwitchUser = (email) => {
if (!this.props.socket || !this.props.socket.connected) {
this.showNotification('Socket not connected', 'error');
return;
}
this.setState({ switchingUser: true }); this.setState({ switchingUser: true });
this.props.socket.emit('switchUser', { email }, (response) => { window.socketManager.emit('switchUser', { email }, (response) => {
console.log('Switch user response:', response); console.log('Switch user response:', response);
this.setState({ switchingUser: false }); this.setState({ switchingUser: false });
@@ -225,14 +209,10 @@ class UsersPage extends React.Component {
} }
handleSwitchBackToAdmin = () => { handleSwitchBackToAdmin = () => {
if (!this.props.socket || !this.props.socket.connected) {
this.showNotification('Socket not connected', 'error');
return;
}
this.setState({ switchingUser: true }); this.setState({ switchingUser: true });
this.props.socket.emit('switchBackToAdmin', (response) => { window.socketManager.emit('switchBackToAdmin', (response) => {
console.log('Switch back to admin response:', response); console.log('Switch back to admin response:', response);
this.setState({ switchingUser: false }); this.setState({ switchingUser: false });

View File

@@ -88,7 +88,7 @@ class TelemetryService {
} }
try { try {
this.socket.emit('telemetry', { window.socketManager.emit('telemetry', {
type: 'consoleLog', type: 'consoleLog',
level: level, level: level,
message: message, message: message,