182 lines
No EOL
6.5 KiB
TypeScript
182 lines
No EOL
6.5 KiB
TypeScript
import { useNavigate, useLocation } from 'react-router-dom';
|
|
import { useState, useEffect } from 'react';
|
|
import { FaGoogle, FaMicrosoft } from 'react-icons/fa';
|
|
|
|
import { useAuth, useMsalAuth } from '../hooks/useAuthentication';
|
|
|
|
import styles from './Login.module.css';
|
|
|
|
|
|
function Login() {
|
|
const navigate = useNavigate();
|
|
const location = useLocation();
|
|
const [username, setUsername] = useState('');
|
|
const [password, setPassword] = useState('');
|
|
const [usernameFocused, setUsernameFocused] = useState(false);
|
|
const [passwordFocused, setPasswordFocused] = useState(false);
|
|
const { login, error: loginError, isLoading: isLoginLoading } = useAuth();
|
|
const { loginWithMsal, error: msalError, isLoading: isMsalLoading } = useMsalAuth();
|
|
|
|
// Get the page the user was trying to visit
|
|
const from = location.state?.from?.pathname || "/";
|
|
|
|
// Set page title
|
|
useEffect(() => {
|
|
document.title = "PowerOn AI Platform - Login";
|
|
}, []);
|
|
|
|
// Check for autofilled inputs
|
|
useEffect(() => {
|
|
const checkAutofill = () => {
|
|
const usernameInput = document.querySelector('input[type="text"]') as HTMLInputElement;
|
|
const passwordInput = document.querySelector('input[type="password"]') as HTMLInputElement;
|
|
|
|
if (usernameInput && usernameInput.value) {
|
|
setUsername(usernameInput.value);
|
|
}
|
|
if (passwordInput && passwordInput.value) {
|
|
setPassword(passwordInput.value);
|
|
}
|
|
};
|
|
|
|
// Check immediately and after a short delay
|
|
checkAutofill();
|
|
const timer = setTimeout(checkAutofill, 100);
|
|
|
|
return () => clearTimeout(timer);
|
|
}, []);
|
|
|
|
const handleMsalLogin = async () => {
|
|
try {
|
|
console.log("Attempting MSAL login...");
|
|
const response = await loginWithMsal();
|
|
console.log("MSAL login successful:", response);
|
|
navigate(from, { replace: true });
|
|
} catch (error) {
|
|
console.error("MSAL login failed:", error);
|
|
}
|
|
};
|
|
|
|
const handleCredentialLogin = async (e?: React.MouseEvent) => {
|
|
e?.preventDefault(); // Prevent default form submission
|
|
try {
|
|
console.log("Attempting login with:", username);
|
|
await login(username, password);
|
|
console.log("Login successful, navigating to:", from);
|
|
// Only navigate if login was successful
|
|
navigate(from, { replace: true });
|
|
} catch (error) {
|
|
console.error("Login failed:", error);
|
|
// Stay on login page to show error message
|
|
// The error will be displayed via the loginError state from useAuth hook
|
|
}
|
|
};
|
|
|
|
return (
|
|
<div className={styles.container}>
|
|
<div className={styles.mainContent}>
|
|
<div className={styles.logo}>
|
|
<div className={styles.logoText}>
|
|
<span className={styles.logoPower}>Power</span>
|
|
<span className={styles.logoOn}>On</span>
|
|
</div>
|
|
</div>
|
|
<div className={styles.loginSection}>
|
|
<div className={styles.loginBox}>
|
|
<div className={styles.loginForm}>
|
|
{(loginError || msalError) && (
|
|
<div className={styles.error}>{loginError || msalError}</div>
|
|
)}
|
|
<div className={styles.floatingLabelInput}>
|
|
<input
|
|
type="text"
|
|
placeholder=" "
|
|
value={username}
|
|
onChange={(e) => setUsername(e.target.value)}
|
|
onFocus={() => setUsernameFocused(true)}
|
|
onBlur={() => setUsernameFocused(false)}
|
|
onKeyDown={(e) => {
|
|
if (e.key === 'Enter') {
|
|
e.preventDefault();
|
|
handleCredentialLogin();
|
|
}
|
|
}}
|
|
className={`${styles.input} ${usernameFocused || username ? styles.focused : ''}`}
|
|
/>
|
|
<label className={usernameFocused || username ? styles.focusedLabel : styles.label}>Benutzername</label>
|
|
</div>
|
|
<div className={styles.floatingLabelInput}>
|
|
<input
|
|
type="password"
|
|
placeholder=" "
|
|
value={password}
|
|
onChange={(e) => setPassword(e.target.value)}
|
|
onFocus={() => setPasswordFocused(true)}
|
|
onBlur={() => setPasswordFocused(false)}
|
|
onKeyDown={(e) => {
|
|
if (e.key === 'Enter') {
|
|
e.preventDefault();
|
|
handleCredentialLogin();
|
|
}
|
|
}}
|
|
className={`${styles.input} ${passwordFocused || password ? styles.focused : ''}`}
|
|
/>
|
|
<label className={passwordFocused || password ? styles.focusedLabel : styles.label}>Passwort</label>
|
|
</div>
|
|
<div className={styles.disclaimer}>
|
|
<p>
|
|
Mit der Anmeldung stimmen Sie unseren Datenschutzbestimmungen zur KI-Nutzung zu.
|
|
</p>
|
|
</div>
|
|
<button
|
|
className={`${styles.button} ${styles.loginButton}`}
|
|
onClick={handleCredentialLogin}
|
|
disabled={isLoginLoading}
|
|
>
|
|
{isLoginLoading ? "wird geladen..." : "Anmelden"}
|
|
</button>
|
|
|
|
<div className={styles.divider}>
|
|
<span>oder</span>
|
|
</div>
|
|
|
|
<button
|
|
className={`${styles.button} ${styles.microsoftButton}`}
|
|
onClick={handleMsalLogin}
|
|
disabled={isMsalLoading}
|
|
>
|
|
<div className={styles.buttonContent}>
|
|
<FaMicrosoft />
|
|
{isMsalLoading ? "Signing in..." : "Mit Microsoft anmelden"}
|
|
</div>
|
|
</button>
|
|
|
|
<button
|
|
className={`${styles.button} ${styles.googleButton}`}
|
|
onClick={() => console.log("Google button clicked")}
|
|
disabled={false}
|
|
>
|
|
<div className={styles.buttonContent}>
|
|
<FaGoogle />
|
|
Mit Google anmelden
|
|
</div>
|
|
</button>
|
|
|
|
<div className={styles.registerLink}>
|
|
<span>Du hast noch keinen Konto?</span>
|
|
<button
|
|
className={styles.textButton}
|
|
onClick={() => navigate("/register")}
|
|
>
|
|
Registrieren
|
|
</button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
export default Login; |