770 lines
25 KiB
JavaScript
770 lines
25 KiB
JavaScript
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 ? (
|
|
<>
|
|
<Button
|
|
variant="text"
|
|
onClick={this.handleUserMenuClick}
|
|
startIcon={<PersonIcon />}
|
|
color={isAdmin ? 'secondary' : 'inherit'}
|
|
sx={{ my: 1, mx: 1.5 }}
|
|
>
|
|
{this.props.t ? this.props.t('auth.profile') : 'Profil'}
|
|
</Button>
|
|
<Menu
|
|
disableScrollLock={true}
|
|
anchorEl={anchorEl}
|
|
open={Boolean(anchorEl)}
|
|
onClose={this.handleUserMenuClose}
|
|
anchorOrigin={{
|
|
vertical: 'bottom',
|
|
horizontal: 'right',
|
|
}}
|
|
transformOrigin={{
|
|
vertical: 'top',
|
|
horizontal: 'right',
|
|
}}
|
|
>
|
|
<MenuItem component={Link} to="/profile" onClick={this.handleUserMenuClose}>
|
|
{this.props.t ? this.props.t('auth.menu.profile') : 'Profil'}
|
|
</MenuItem>
|
|
<MenuItem component={Link} to="/profile#cart" onClick={this.handleUserMenuClose} sx={{ pl: 4 }}>
|
|
{this.props.t ? this.props.t('auth.menu.checkout') : 'Bestellabschluss'}
|
|
</MenuItem>
|
|
<MenuItem component={Link} to="/profile#orders" onClick={this.handleUserMenuClose} sx={{ pl: 4 }}>
|
|
{this.props.t ? this.props.t('auth.menu.orders') : 'Bestellungen'}
|
|
</MenuItem>
|
|
<MenuItem component={Link} to="/profile#settings" onClick={this.handleUserMenuClose} sx={{ pl: 4 }}>
|
|
{this.props.t ? this.props.t('auth.menu.settings') : 'Einstellungen'}
|
|
</MenuItem>
|
|
<Divider />
|
|
{isAdmin ? <MenuItem component={Link} to="/admin" onClick={this.handleUserMenuClose}>
|
|
{this.props.t ? this.props.t('auth.menu.adminDashboard') : 'Admin Dashboard'}
|
|
</MenuItem> : null}
|
|
{isAdmin ? <MenuItem component={Link} to="/admin/users" onClick={this.handleUserMenuClose}>
|
|
{this.props.t ? this.props.t('auth.menu.adminUsers') : 'Admin Users'}
|
|
</MenuItem> : null}
|
|
<MenuItem onClick={this.handleLogout}>
|
|
{this.props.t ? this.props.t('auth.logout') : 'Abmelden'}
|
|
</MenuItem>
|
|
</Menu>
|
|
</>
|
|
) : (
|
|
<Button
|
|
variant="outlined"
|
|
color="inherit"
|
|
onClick={this.handleOpen}
|
|
sx={{ my: 1, mx: 1.5 }}
|
|
>
|
|
{this.props.t ? this.props.t('auth.login') : 'Login'}
|
|
</Button>
|
|
)
|
|
)}
|
|
|
|
<Dialog
|
|
open={open}
|
|
onClose={handleCloseProp || this.handleClose}
|
|
disableScrollLock
|
|
fullWidth
|
|
maxWidth="xs"
|
|
>
|
|
<DialogTitle sx={{ bgcolor: 'white', pb: 0 }}>
|
|
<Box display="flex" justifyContent="space-between" alignItems="center">
|
|
<Typography variant="h6" color="#2e7d32" fontWeight="bold">
|
|
{tabValue === 0 ?
|
|
(this.props.t ? this.props.t('auth.login') : 'Anmelden') :
|
|
(this.props.t ? this.props.t('auth.register') : 'Registrieren')
|
|
}
|
|
</Typography>
|
|
<IconButton edge="end" onClick={this.handleClose} aria-label="close">
|
|
<CloseIcon />
|
|
</IconButton>
|
|
</Box>
|
|
</DialogTitle>
|
|
|
|
<DialogContent>
|
|
<Tabs
|
|
value={tabValue}
|
|
onChange={this.handleTabChange}
|
|
variant="fullWidth"
|
|
sx={{ mb: 2 }}
|
|
TabIndicatorProps={{
|
|
style: { backgroundColor: '#2e7d32' }
|
|
}}
|
|
textColor="inherit"
|
|
>
|
|
<Tab
|
|
label={this.props.t ? this.props.t('auth.login').toUpperCase() : "ANMELDEN"}
|
|
sx={{
|
|
color: tabValue === 0 ? '#2e7d32' : 'inherit',
|
|
fontWeight: 'bold'
|
|
}}
|
|
/>
|
|
<Tab
|
|
label={this.props.t ? this.props.t('auth.register').toUpperCase() : "REGISTRIEREN"}
|
|
sx={{
|
|
color: tabValue === 1 ? '#2e7d32' : 'inherit',
|
|
fontWeight: 'bold'
|
|
}}
|
|
/>
|
|
</Tabs>
|
|
|
|
|
|
{/* Google Sign In Button */}
|
|
<Box sx={{ width: '100%', display: 'flex', flexDirection: 'column', alignItems: 'center', mb: 2 }}>
|
|
{!privacyConfirmed && (
|
|
<Typography variant="caption" sx={{ mb: 1, textAlign: 'center' }}>
|
|
{this.props.t ?
|
|
<>
|
|
{this.props.t('auth.privacyAccept')} <Link to="/datenschutz" style={{ color: '#4285F4' }}>{this.props.t('auth.privacyPolicy')}</Link>
|
|
</> :
|
|
<>
|
|
Mit dem Click auf "Mit Google anmelden" akzeptiere ich die <Link to="/datenschutz" style={{ color: '#4285F4' }}>Datenschutzbestimmungen</Link>
|
|
</>
|
|
}
|
|
</Typography>
|
|
)}
|
|
{!showGoogleAuth && (
|
|
<Button
|
|
variant="contained"
|
|
startIcon={<PersonIcon />}
|
|
onClick={() => {
|
|
sessionStorage.setItem('privacyConfirmed', 'true');
|
|
this.setState({ showGoogleAuth: true, privacyConfirmed: true });
|
|
}}
|
|
sx={{ width: '100%', backgroundColor: '#4285F4', color: 'white' }}
|
|
>
|
|
{this.props.t ? this.props.t('auth.loginWithGoogle') : 'Mit Google anmelden'}
|
|
</Button>
|
|
)}
|
|
|
|
{showGoogleAuth && (
|
|
<Suspense fallback={
|
|
<Button
|
|
variant="contained"
|
|
startIcon={<PersonIcon />}
|
|
sx={{ width: '100%', backgroundColor: '#4285F4', color: 'white' }}
|
|
>
|
|
Mit Google anmelden
|
|
</Button>
|
|
}>
|
|
<GoogleAuthProvider clientId={config.googleClientId}>
|
|
<GoogleLoginButton
|
|
onSuccess={this.handleGoogleLoginSuccess}
|
|
onError={this.handleGoogleLoginError}
|
|
text="Mit Google anmelden"
|
|
style={{ width: '100%', backgroundColor: '#4285F4' }}
|
|
autoInitiate={true}
|
|
/>
|
|
</GoogleAuthProvider>
|
|
</Suspense>
|
|
)}
|
|
</Box>
|
|
|
|
|
|
|
|
{/* OR Divider */}
|
|
<Box sx={{ display: 'flex', alignItems: 'center', my: 2 }}>
|
|
<Box sx={{ flex: 1, height: '1px', backgroundColor: '#e0e0e0' }} />
|
|
<Typography variant="body2" sx={{ px: 2, color: '#757575' }}>
|
|
{this.props.t ? this.props.t('auth.or') : 'ODER'}
|
|
</Typography>
|
|
<Box sx={{ flex: 1, height: '1px', backgroundColor: '#e0e0e0' }} />
|
|
</Box>
|
|
|
|
{error && <Alert severity="error" sx={{ mb: 2 }}>{error}</Alert>}
|
|
{success && <Alert severity="success" sx={{ mb: 2 }}>{success}</Alert>}
|
|
|
|
|
|
<Box sx={{ py: 1 }}>
|
|
<TextField
|
|
margin="dense"
|
|
label={this.props.t ? this.props.t('auth.email') : 'E-Mail'}
|
|
type="email"
|
|
fullWidth
|
|
variant="outlined"
|
|
value={email}
|
|
onChange={(e) => this.setState({ email: e.target.value })}
|
|
disabled={loading}
|
|
/>
|
|
|
|
<TextField
|
|
margin="dense"
|
|
label={this.props.t ? this.props.t('auth.password') : 'Passwort'}
|
|
type="password"
|
|
fullWidth
|
|
variant="outlined"
|
|
value={password}
|
|
onChange={(e) => this.setState({ password: e.target.value })}
|
|
disabled={loading}
|
|
/>
|
|
|
|
{tabValue === 0 && (
|
|
<Box sx={{ display: 'flex', justifyContent: 'flex-end', mt: 1, mb: 1 }}>
|
|
<Button
|
|
variant="text"
|
|
size="small"
|
|
onClick={this.handleForgotPassword}
|
|
disabled={loading}
|
|
sx={{
|
|
color: '#2e7d32',
|
|
textTransform: 'none',
|
|
'&:hover': { backgroundColor: 'transparent', textDecoration: 'underline' }
|
|
}}
|
|
>
|
|
{this.props.t ? this.props.t('auth.forgotPassword') : 'Passwort vergessen?'}
|
|
</Button>
|
|
</Box>
|
|
)}
|
|
|
|
{tabValue === 1 && (
|
|
<TextField
|
|
margin="dense"
|
|
label={this.props.t ? this.props.t('auth.confirmPassword') : 'Passwort bestätigen'}
|
|
type="password"
|
|
fullWidth
|
|
variant="outlined"
|
|
value={confirmPassword}
|
|
onChange={(e) => this.setState({ confirmPassword: e.target.value })}
|
|
disabled={loading}
|
|
/>
|
|
)}
|
|
|
|
{loading ? (
|
|
<Box display="flex" justifyContent="center" mt={2}>
|
|
<CircularProgress size={24} />
|
|
</Box>
|
|
) : (
|
|
<Button
|
|
variant="contained"
|
|
color="primary"
|
|
fullWidth
|
|
onClick={tabValue === 0 ? this.handleLogin : this.handleRegister}
|
|
sx={{ mt: 2, bgcolor: '#2e7d32', '&:hover': { bgcolor: '#1b5e20' } }}
|
|
>
|
|
{tabValue === 0 ? (this.props.t ? this.props.t('auth.login').toUpperCase() : 'ANMELDEN') : (this.props.t ? this.props.t('auth.register').toUpperCase() : 'REGISTRIEREN')}
|
|
</Button>
|
|
)}
|
|
</Box>
|
|
</DialogContent>
|
|
</Dialog>
|
|
<CartSyncDialog
|
|
open={cartSyncOpen}
|
|
localCart={localCartSync}
|
|
serverCart={serverCartSync}
|
|
onClose={() => {
|
|
const { pendingNavigate } = this.state;
|
|
this.setState({ cartSyncOpen: false, pendingNavigate: null });
|
|
this.handleClose();
|
|
if (pendingNavigate) pendingNavigate();
|
|
}}
|
|
onConfirm={this.handleCartSyncConfirm}
|
|
/>
|
|
</>
|
|
);
|
|
}
|
|
}
|
|
|
|
export default withRouter(withI18n()(LoginComponent));
|