import React, { lazy, Component, Suspense } from 'react'; import { Link } from 'react-router-dom'; import Box from '@mui/material/Box'; import Button from '@mui/material/Button'; import Dialog from '@mui/material/Dialog'; import DialogTitle from '@mui/material/DialogTitle'; import DialogContent from '@mui/material/DialogContent'; import Tabs from '@mui/material/Tabs'; import Tab from '@mui/material/Tab'; import TextField from '@mui/material/TextField'; import IconButton from '@mui/material/IconButton'; import Typography from '@mui/material/Typography'; import Alert from '@mui/material/Alert'; import CircularProgress from '@mui/material/CircularProgress'; import MenuItem from '@mui/material/MenuItem'; import Menu from '@mui/material/Menu'; import Divider from '@mui/material/Divider'; import CloseIcon from '@mui/icons-material/Close'; import PersonIcon from '@mui/icons-material/Person'; import { withRouter } from './withRouter.js'; import GoogleLoginButton from './GoogleLoginButton.js'; import CartSyncDialog from './CartSyncDialog.js'; import { localAndArchiveServer, mergeCarts } from '../utils/cartUtils.js'; import config from '../config.js'; import { withI18n } from '../i18n/withTranslation.js'; // Lazy load GoogleAuthProvider const GoogleAuthProvider = lazy(() => import('../providers/GoogleAuthProvider.js')); // Function to check if user is logged in export const isUserLoggedIn = () => { const storedUser = sessionStorage.getItem('user'); if (storedUser) { try { const parsedUser = JSON.parse(storedUser); console.log('Parsed User:', parsedUser); return { isLoggedIn: true, user: parsedUser, isAdmin: !!parsedUser.admin }; } catch (error) { console.error('Error parsing user from sessionStorage:', error); sessionStorage.removeItem('user'); } } console.log('isUserLoggedIn', false); return { isLoggedIn: false, user: null, isAdmin: false }; }; // Hilfsfunktion zum Vergleich zweier Cart-Arrays function cartsAreIdentical(cartA, cartB) { console.log('Vergleiche Carts:', {cartA, cartB}); if (!Array.isArray(cartA) || !Array.isArray(cartB)) { console.log('Mindestens eines der Carts ist kein Array'); return false; } if (cartA.length !== cartB.length) { console.log('Unterschiedliche Längen:', cartA.length, cartB.length); return false; } const sortById = arr => [...arr].sort((a, b) => (a.id > b.id ? 1 : -1)); const aSorted = sortById(cartA); const bSorted = sortById(cartB); for (let i = 0; i < aSorted.length; i++) { if (aSorted[i].id !== bSorted[i].id) { console.log('Unterschiedliche IDs:', aSorted[i].id, bSorted[i].id, aSorted[i], bSorted[i]); return false; } if (aSorted[i].quantity !== bSorted[i].quantity) { console.log('Unterschiedliche Mengen:', aSorted[i].id, aSorted[i].quantity, bSorted[i].quantity); return false; } } console.log('Carts sind identisch'); return true; } export class LoginComponent extends Component { constructor(props) { super(props); this.state = { open: false, tabValue: 0, email: '', password: '', confirmPassword: '', error: '', loading: false, success: '', isLoggedIn: false, isAdmin: false, user: null, anchorEl: null, showGoogleAuth: false, cartSyncOpen: false, localCartSync: [], serverCartSync: [], pendingNavigate: null, privacyConfirmed: sessionStorage.getItem('privacyConfirmed') === 'true' }; } componentDidMount() { // Make the open function available globally window.openLoginDrawer = this.handleOpen; // Check if user is logged in const { isLoggedIn: userIsLoggedIn, user: storedUser } = isUserLoggedIn(); if (userIsLoggedIn) { this.setState({ user: storedUser, isAdmin: !!storedUser.admin, isLoggedIn: true }); } if (this.props.open) { this.setState({ open: true }); } } componentDidUpdate(prevProps) { if (this.props.open !== prevProps.open) { this.setState({ open: this.props.open }); } } componentWillUnmount() { // Cleanup function to remove global reference when component unmounts window.openLoginDrawer = undefined; } resetForm = () => { this.setState({ email: '', password: '', confirmPassword: '', error: '', success: '', loading: false, showGoogleAuth: false // Reset Google auth state when form is reset }); }; handleOpen = () => { this.setState({ open: true, loading: false, privacyConfirmed: sessionStorage.getItem('privacyConfirmed') === 'true' }); this.resetForm(); }; handleClose = () => { this.setState({ open: false, showGoogleAuth: false // Reset Google auth state when dialog closes }); this.resetForm(); }; handleTabChange = (event, newValue) => { this.setState({ tabValue: newValue, error: '', success: '' }); }; validateEmail = (email) => { return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email); }; handleLogin = () => { const { email, password } = this.state; const { socket, location, navigate } = this.props; if (!email || !password) { this.setState({ error: 'Bitte füllen Sie alle Felder aus' }); return; } if (!this.validateEmail(email)) { this.setState({ error: 'Bitte geben Sie eine gültige E-Mail-Adresse ein' }); return; } this.setState({ loading: true, error: '' }); // Call verifyUser socket endpoint if (!socket || !socket.connected) { this.setState({ loading: false, error: 'Verbindung zum Server verloren. Bitte versuchen Sie es erneut.' }); return; } socket.emit('verifyUser', { email, password }, (response) => { console.log('LoginComponent: verifyUser', response); if (response.success) { sessionStorage.setItem('user', JSON.stringify(response.user)); this.setState({ user: response.user, isLoggedIn: true, isAdmin: !!response.user.admin }); const redirectTo = location && location.hash ? `/profile${location.hash}` : '/profile'; const dispatchLoginEvent = () => { window.dispatchEvent(new CustomEvent('userLoggedIn')); navigate(redirectTo); } try { const newCart = JSON.parse(response.user.cart); const localCartArr = window.cart ? Object.values(window.cart) : []; const serverCartArr = newCart ? Object.values(newCart) : []; if (serverCartArr.length === 0) { if (socket && socket.connected) { socket.emit('updateCart', window.cart); } this.handleClose(); dispatchLoginEvent(); } else if (localCartArr.length === 0 && serverCartArr.length > 0) { window.cart = serverCartArr; window.dispatchEvent(new CustomEvent('cart')); this.handleClose(); dispatchLoginEvent(); } else if (cartsAreIdentical(localCartArr, serverCartArr)) { this.handleClose(); dispatchLoginEvent(); } else { this.setState({ cartSyncOpen: true, localCartSync: localCartArr, serverCartSync: serverCartArr, pendingNavigate: dispatchLoginEvent }); } } catch (error) { console.error('Error parsing cart:', response.user, error); this.handleClose(); dispatchLoginEvent(); } } else { this.setState({ loading: false, error: response.message || 'Anmeldung fehlgeschlagen' }); } }); }; handleRegister = () => { const { email, password, confirmPassword } = this.state; const { socket } = this.props; if (!email || !password || !confirmPassword) { this.setState({ error: 'Bitte füllen Sie alle Felder aus' }); return; } if (!this.validateEmail(email)) { this.setState({ error: 'Bitte geben Sie eine gültige E-Mail-Adresse ein' }); return; } if (password !== confirmPassword) { this.setState({ error: 'Passwörter stimmen nicht überein' }); return; } if (password.length < 8) { this.setState({ error: 'Das Passwort muss mindestens 8 Zeichen lang sein' }); return; } this.setState({ loading: true, error: '' }); // Call createUser socket endpoint if (!socket || !socket.connected) { this.setState({ loading: false, error: 'Verbindung zum Server verloren. Bitte versuchen Sie es erneut.' }); return; } socket.emit('createUser', { email, password }, (response) => { if (response.success) { this.setState({ loading: false, success: 'Registrierung erfolgreich. Sie können sich jetzt anmelden.', tabValue: 0 // Switch to login tab }); } else { this.setState({ loading: false, error: response.message || 'Registrierung fehlgeschlagen' }); } }); }; handleUserMenuClick = (event) => { this.setState({ anchorEl: event.currentTarget }); }; handleUserMenuClose = () => { this.setState({ anchorEl: null }); }; handleLogout = () => { if (!this.props.socket || !this.props.socket.connected) { // If socket is not connected, just clear local storage sessionStorage.removeItem('user'); window.cart = []; window.dispatchEvent(new CustomEvent('cart')); window.dispatchEvent(new CustomEvent('userLoggedOut')); this.setState({ isLoggedIn: false, user: null, isAdmin: false, anchorEl: null }); return; } this.props.socket.emit('logout', (response) => { if(response.success){ sessionStorage.removeItem('user'); window.dispatchEvent(new CustomEvent('userLoggedIn')); this.props.navigate('/'); this.setState({ user: null, isLoggedIn: false, isAdmin: false, anchorEl: null, }); } }); }; handleForgotPassword = () => { const { email } = this.state; const { socket } = this.props; if (!email) { this.setState({ error: 'Bitte geben Sie Ihre E-Mail-Adresse ein' }); return; } if (!this.validateEmail(email)) { this.setState({ error: 'Bitte geben Sie eine gültige E-Mail-Adresse ein' }); return; } this.setState({ loading: true, error: '' }); // Call resetPassword socket endpoint socket.emit('resetPassword', { email, domain: window.location.origin }, (response) => { console.log('Reset Password Response:', response); if (response.success) { this.setState({ loading: false, success: 'Ein Link zum Zurücksetzen des Passworts wurde an Ihre E-Mail-Adresse gesendet.' }); } else { this.setState({ loading: false, error: response.message || 'Fehler beim Senden der E-Mail' }); } }); }; // Google login functionality handleGoogleLoginSuccess = (credentialResponse) => { const { socket, location, navigate } = this.props; this.setState({ loading: true, error: '' }); console.log('beforeG',credentialResponse) socket.emit('verifyGoogleUser', { credential: credentialResponse.credential }, (response) => { console.log('google respo',response); if (response.success) { sessionStorage.setItem('user', JSON.stringify(response.user)); this.setState({ isLoggedIn: true, isAdmin: !!response.user.admin, user: response.user }); const redirectTo = location && location.hash ? `/profile${location.hash}` : '/profile'; const dispatchLoginEvent = () => { window.dispatchEvent(new CustomEvent('userLoggedIn')); navigate(redirectTo); }; try { const newCart = JSON.parse(response.user.cart); const localCartArr = window.cart ? Object.values(window.cart) : []; const serverCartArr = newCart ? Object.values(newCart) : []; if (serverCartArr.length === 0) { socket.emit('updateCart', window.cart); this.handleClose(); dispatchLoginEvent(); } else if (localCartArr.length === 0 && serverCartArr.length > 0) { window.cart = serverCartArr; window.dispatchEvent(new CustomEvent('cart')); this.handleClose(); dispatchLoginEvent(); } else if (cartsAreIdentical(localCartArr, serverCartArr)) { this.handleClose(); dispatchLoginEvent(); } else { this.setState({ cartSyncOpen: true, localCartSync: localCartArr, serverCartSync: serverCartArr, pendingNavigate: dispatchLoginEvent }); } } catch (error) { console.error('Error parsing cart:', response.user, error); this.handleClose(); dispatchLoginEvent(); } } else { this.setState({ loading: false, error: 'Google-Anmeldung fehlgeschlagen', showGoogleAuth: false // Reset Google auth state on failed login }); } }); }; handleGoogleLoginError = (error) => { console.error('Google Login Error:', error); this.setState({ error: 'Google-Anmeldung fehlgeschlagen', showGoogleAuth: false, // Reset Google auth state on error loading: false }); }; handleCartSyncConfirm = async (option) => { const { localCartSync, serverCartSync, pendingNavigate } = this.state; switch (option) { case 'useLocalArchive': localAndArchiveServer(localCartSync, serverCartSync); break; case 'deleteServer': this.props.socket.emit('updateCart', window.cart) break; case 'useServer': window.cart = serverCartSync; break; case 'merge': default: { const merged = mergeCarts(localCartSync, serverCartSync); console.log('MERGED CART RESULT:', merged); window.cart = merged; break; } } window.dispatchEvent(new CustomEvent('cart')); this.setState({ cartSyncOpen: false, localCartSync: [], serverCartSync: [], pendingNavigate: null }); this.handleClose(); if (pendingNavigate) pendingNavigate(); }; render() { const { open, tabValue, email, password, confirmPassword, error, loading, success, isLoggedIn, isAdmin, anchorEl, showGoogleAuth, cartSyncOpen, localCartSync, serverCartSync, privacyConfirmed } = this.state; const { open: openProp, handleClose: handleCloseProp } = this.props; const isExternallyControlled = openProp !== undefined; return ( <> {!isExternallyControlled && ( isLoggedIn ? ( <> } color={isAdmin ? 'secondary' : 'inherit'} sx={{ my: 1, mx: 1.5 }} > {this.props.t ? this.props.t('auth.profile') : 'Profil'}
> ) : ( ) )}