diff --git a/frontend/app/components/Login/Login.js b/frontend/app/components/Login/Login.js
deleted file mode 100644
index 69c8fb521..000000000
--- a/frontend/app/components/Login/Login.js
+++ /dev/null
@@ -1,224 +0,0 @@
-import React from 'react';
-import { connect } from 'react-redux';
-import withPageTitle from 'HOCs/withPageTitle';
-import { Icon, Loader, Button, Link, Input, Form, Popover, Tooltip } from 'UI';
-import { login } from 'Duck/user';
-import { forgotPassword, signup } from 'App/routes';
-import ReCAPTCHA from 'react-google-recaptcha';
-import { withRouter } from 'react-router-dom';
-import stl from './login.module.css';
-import cn from 'classnames';
-import { setJwt } from 'Duck/user';
-import LoginBg from '../../svg/login-illustration.svg';
-import { ENTERPRISE_REQUEIRED } from 'App/constants';
-import { fetchTenants } from 'Duck/user';
-import Copyright from 'Shared/Copyright';
-
-const FORGOT_PASSWORD = forgotPassword();
-const SIGNUP_ROUTE = signup();
-const recaptchaRef = React.createRef();
-
-export default
-@connect(
- (state, props) => ({
- errors: state.getIn(['user', 'loginRequest', 'errors']),
- loading: state.getIn(['user', 'loginRequest', 'loading']),
- authDetails: state.getIn(['user', 'authDetails']),
- params: new URLSearchParams(props.location.search),
- }),
- { login, setJwt, fetchTenants }
-)
-@withPageTitle('Login - OpenReplay')
-@withRouter
-class Login extends React.Component {
- state = {
- email: '',
- password: '',
- CAPTCHA_ENABLED: window.env.CAPTCHA_ENABLED === 'true',
- };
-
- static getDerivedStateFromProps(nextProps, prevState) {
- const { authDetails } = nextProps;
- if (Object.keys(authDetails).length === 0) {
- return null;
- }
-
- if (!authDetails.tenants) {
- nextProps.history.push(SIGNUP_ROUTE);
- }
-
- return null;
- }
-
- componentDidMount() {
- const { params } = this.props;
- this.props.fetchTenants();
- const jwt = params.get('jwt');
- if (jwt) {
- this.props.setJwt(jwt);
- }
- }
-
- handleSubmit = (token) => {
- const { email, password } = this.state;
- this.props.login({ email: email.trim(), password, 'g-recaptcha-response': token });
- };
-
- onSubmit = (e) => {
- e.preventDefault();
- const { CAPTCHA_ENABLED } = this.state;
- if (CAPTCHA_ENABLED && recaptchaRef.current) {
- recaptchaRef.current.execute();
- } else if (!CAPTCHA_ENABLED) {
- this.handleSubmit();
- }
- };
-
- write = ({ target: { value, name } }) => this.setState({ [name]: value });
-
- render() {
- const { errors, loading, authDetails } = this.props;
- const { CAPTCHA_ENABLED } = this.state;
-
- return (
-
-
-
-

-
-
-
- Login to your account
-
-
-
-
-
- }
- placement="top"
- >
-
-
- )}
-
-
-
-
-
-
-
-
- );
- }
-}
diff --git a/frontend/app/components/Login/Login.tsx b/frontend/app/components/Login/Login.tsx
new file mode 100644
index 000000000..e4140308f
--- /dev/null
+++ b/frontend/app/components/Login/Login.tsx
@@ -0,0 +1,229 @@
+import React, {useState, useEffect, useRef} from 'react';
+// import {useSelector, useDispatch} from 'react-redux';
+import {useHistory, useLocation} from 'react-router-dom';
+import {login, setJwt, fetchTenants} from 'Duck/user';
+import withPageTitle from 'HOCs/withPageTitle'; // Consider using a different approach for titles in functional components
+import ReCAPTCHA from 'react-google-recaptcha';
+import {Button, Form, Input, Link, Loader, Popover, Tooltip, Icon} from 'UI';
+import {forgotPassword, signup} from 'App/routes';
+import LoginBg from '../../svg/login-illustration.svg';
+import {ENTERPRISE_REQUEIRED} from 'App/constants';
+import cn from 'classnames';
+import stl from './login.module.css';
+import Copyright from 'Shared/Copyright';
+import {connect} from 'react-redux';
+
+const FORGOT_PASSWORD = forgotPassword();
+const SIGNUP_ROUTE = signup();
+
+interface LoginProps {
+ errors: any; // Adjust the type based on your state shape
+ loading: boolean;
+ authDetails: any; // Adjust the type based on your state shape
+ login: typeof login;
+ setJwt: typeof setJwt;
+ fetchTenants: typeof fetchTenants;
+ location: Location;
+}
+
+const Login: React.FC = ({errors, loading, authDetails, login, setJwt, fetchTenants, location}) => {
+ const [email, setEmail] = useState('');
+ const [password, setPassword] = useState('');
+ const [CAPTCHA_ENABLED, setCAPTCHA_ENABLED] = useState(window.env.CAPTCHA_ENABLED === 'true');
+ const recaptchaRef = useRef(null);
+
+ const history = useHistory();
+ const params = new URLSearchParams(location.search);
+
+ useEffect(() => {
+ if (Object.keys(authDetails).length !== 0) {
+ if (!authDetails.tenants) {
+ history.push(SIGNUP_ROUTE);
+ }
+ }
+ }, [authDetails]);
+
+ useEffect(() => {
+ fetchTenants()
+ const jwt = params.get('jwt');
+ if (jwt) {
+ setJwt(jwt);
+ }
+ }, []);
+
+ const handleSubmit = (token?: string) => {
+ login({email: email.trim(), password, 'g-recaptcha-response': token});
+ };
+
+ const onSubmit = (e: React.FormEvent) => {
+ e.preventDefault();
+ if (CAPTCHA_ENABLED && recaptchaRef.current) {
+ recaptchaRef.current.execute();
+ } else if (!CAPTCHA_ENABLED) {
+ handleSubmit();
+ }
+ };
+
+ const onSSOClick = () => {
+ if (window !== window.top) { // if in iframe
+ window.parent.location.href = `${window.location.origin}/api/sso/saml2?iFrame=true`;
+ } else {
+ window.location.href = `${window.location.origin}/api/sso/saml2`;
+ }
+ };
+
+ return (
+
+
+
+

+
+
+
+ Login to your account
+
+
+
+
+
+ }
+ placement="top"
+ >
+
+
+ )}
+
+
+
+
+
+
+
+
+ );
+};
+
+const mapStateToProps = (state: any, ownProps: any) => ({
+ errors: state.getIn(['user', 'loginRequest', 'errors']),
+ loading: state.getIn(['user', 'loginRequest', 'loading']),
+ authDetails: state.getIn(['user', 'authDetails']),
+ params: new URLSearchParams(ownProps.location.search),
+});
+
+const mapDispatchToProps = {
+ login,
+ setJwt,
+ fetchTenants,
+};
+
+export default withPageTitle('Login - OpenReplay')(
+ connect(mapStateToProps, mapDispatchToProps)(Login)
+);
\ No newline at end of file