/* * Copyright (c) 2026 by Christian Kellner. * Licensed under Apache-2.0 with Commons Clause and Attribution/Naming Clause */ import React, { useEffect } from 'react'; import cityBackground from '../../assets/city_background.jpg'; import Logo from '../../components/logo/Logo'; import { xhrPost } from '../../services/xhr'; import { useLocation, useNavigate } from 'react-router-dom'; import { useActions, useSelector } from '../../services/state/store'; import { Input, Button, Banner } from '@douyinfe/semi-ui-19'; import './login.less'; import { IconUser, IconLock } from '@douyinfe/semi-icons'; import { useTranslation } from '../../services/i18n/i18n.jsx'; export default function Login() { const t = useTranslation(); const actions = useActions(); const [username, setUserName] = React.useState(''); const [password, setPassword] = React.useState(''); const [error, setError] = React.useState(null); const demoMode = useSelector((state) => state.demoMode.demoMode || false); const navigate = useNavigate(); const location = useLocation(); useEffect(() => { async function init() { await actions.demoMode.getDemoMode(); } init(); }, []); const tryLogin = async () => { if (!username?.trim() || !password) { setError(t('login.errorMandatory')); return; } setError(null); try { await xhrPost('/api/login', { username: username.trim(), password, }); /* eslint-disable no-unused-vars */ } catch (ignored) { setError(t('login.errorInvalid')); return; } await actions.user.getCurrentUser(); navigate(location.state?.from?.pathname || '/dashboard'); }; return (
{demoMode && ( )}
e.preventDefault()}> {error && }
} placeholder={t('login.usernamePlaceholder')} value={username} showClear autoFocus onChange={(value) => setUserName(value)} onKeyPress={async (e) => { if (e.key === 'Enter') { await tryLogin(); } }} />
} value={password} placeholder={t('login.passwordPlaceholder')} onChange={(value) => setPassword(value)} onKeyPress={async (e) => { if (e.key === 'Enter') { await tryLogin(); } }} />
); } Login.displayName = 'Login';