CI / Generate TypeScript types (push) Successful in 12s
CI / Server unit tests (push) Successful in 26s
CI / Build server (push) Successful in 32s
CI / Build client (push) Successful in 41s
CI / Playwright E2E tests (push) Successful in 1m47s
CI / Build and push Docker image (push) Successful in 49s
CI / Notify (push) Successful in 2s
103 lines
3.6 KiB
TypeScript
103 lines
3.6 KiB
TypeScript
import React, { useCallback, useEffect, useRef, useState } from 'react';
|
|
import { Button } from 'react-bootstrap';
|
|
import { useAuth } from './context/auth';
|
|
import { login } from '../../types';
|
|
import { useAppConfig } from './hooks/useGroupLimits';
|
|
import './Login.css';
|
|
|
|
/**
|
|
* Přihlášení. Podle konfigurace serveru buď přihlásí uživatele automaticky přes důvěryhodné
|
|
* hlavičky z proxy (bez formuláře), nebo zobrazí formulář pro zadání jména. Když se konfigurace
|
|
* nenačte, zkusí nejprve přihlášení „naprázdno" a jinak zobrazí formulář (původní chování).
|
|
*/
|
|
export default function Login() {
|
|
const auth = useAuth();
|
|
const { loaded, trustedHeaders } = useAppConfig();
|
|
const loginRef = useRef<HTMLInputElement>(null);
|
|
const [trustedError, setTrustedError] = useState<string>();
|
|
const [attempt, setAttempt] = useState(0);
|
|
|
|
useEffect(() => {
|
|
if (!auth || auth.login || !loaded || trustedHeaders === false) return;
|
|
// Přihlášení přes hlavičky z proxy (případně pokus „naprázdno", pokud nevíme, jak server přihlašuje)
|
|
setTrustedError(undefined);
|
|
login().then(response => {
|
|
const token = response.data;
|
|
if (token) {
|
|
auth.setToken(token as unknown as string); // TODO vyřešit, API definice je špatně, je to skutečně string
|
|
} else if (trustedHeaders) {
|
|
setTrustedError((response.error as any)?.error ?? 'Přihlášení přes proxy se nezdařilo.');
|
|
}
|
|
}).catch(() => {
|
|
if (trustedHeaders) setTrustedError('Server je nedostupný. Zkuste to prosím za chvíli.');
|
|
});
|
|
}, [auth, loaded, trustedHeaders, attempt]);
|
|
|
|
const doLogin = useCallback(async () => {
|
|
const length = loginRef?.current?.value.length && loginRef.current.value.replaceAll(/\s/g, '').length
|
|
if (length) {
|
|
const response = await login({ body: { login: loginRef.current?.value } });
|
|
if (response.data) {
|
|
auth?.setToken(response.data as unknown as string); // TODO vyřešit
|
|
}
|
|
}
|
|
}, [auth]);
|
|
|
|
if (auth?.login) {
|
|
return <div>Neplatný stav</div>
|
|
}
|
|
|
|
const header = <>
|
|
<h1 className='login-logo'>Luncher</h1>
|
|
<p className='login-subtitle'>Aplikace pro profesionální management obědů</p>
|
|
</>;
|
|
|
|
// Přihlašuje proxy — formulář se jménem nedává smysl
|
|
if (!loaded || trustedHeaders) {
|
|
return (
|
|
<div className='login-page'>
|
|
<div className='login-card'>
|
|
{header}
|
|
{trustedError ? (
|
|
<div className='login-form'>
|
|
<p className='login-error'>{trustedError}</p>
|
|
<Button onClick={() => setAttempt(a => a + 1)}>Zkusit znovu</Button>
|
|
</div>
|
|
) : (
|
|
<p className='hint'>Přihlašuji…</p>
|
|
)}
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className='login-page'>
|
|
<div className='login-card'>
|
|
{header}
|
|
<div className='login-form'>
|
|
<div>
|
|
<label htmlFor="login-input">Zobrazované jméno</label>
|
|
<input
|
|
id="login-input"
|
|
ref={loginRef}
|
|
type='text'
|
|
placeholder="Např. Jan Novák"
|
|
onKeyDown={event => {
|
|
if (event.key === 'Enter') {
|
|
doLogin()
|
|
}
|
|
}}
|
|
/>
|
|
<p className='hint'>
|
|
Zadejte jméno nebo přezdívku, pod kterou vás kolegové snadno identifikují.
|
|
Jméno je možné kdykoli změnit.
|
|
</p>
|
|
</div>
|
|
<Button onClick={doLogin}>Pokračovat</Button>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
);
|
|
}
|