wuespace/telestion-client

View on GitHub
packages/telestion-client-common/src/components/pages/login-page/login-form/form/form.tsx

Summary

Maintainability
A
2 hrs
Test Coverage
/* eslint-disable max-lines-per-function */
import { useCallback, useState } from 'react';
import { Form as RSForm, View } from '@adobe/react-spectrum';

import { FormProps } from './form.model';
import { TextField } from './text-field';
import { LoginButton } from './login-button';
import { isValidHttpUrl, isValidText } from './validate-inputs';

/**
 * The form component that renders the react-spectrum login form
 * where the user enters his information and credentials to log in with.
 *
 * The user submits their login information
 * via the {@link FormProps.onSubmit} event.
 *
 * If the loading state is `true` all user input is blocked.
 *
 * @see {@link FormProps}
 *
 * @example
 * ```ts
 * function MyForm() {
 *     const [isLoading, setIsLoading] = useState(false);
 *
 *     const handleSubmit = (submission: Submission) => {
 *         setIsLoading(true);
 *         alert(`User ${submission.username} tries to log in!`);
 *         setTimeout(() => setIsLoading(false), 1000);
 *     };
 *
 *     return <Form isLoading={isLoading} onSubmit={handleSubmit} />;
 * }
 * ```
 */
export function Form({
    isLoading,
    onSubmit,
    initialServerURL = '',
    initialUsername = ''
}: FormProps) {
    const [serverUrl, setServerUrl] = useState<string | null>('');
    const [username, setUsername] = useState<string | null>('');
    const [password, setPassword] = useState<string | null>('');

    const login = useCallback(() => {
        if (serverUrl && username && password) {
            onSubmit({ serverUrl, username, password });
        }
    }, [onSubmit, password, serverUrl, username]);

    const [focused, setFocused] = useState(() => {
        if (initialUsername) return 2;
        if (initialServerURL) return 1;
        return 0;
    });

    return (
        <>
            <RSForm
                maxWidth="100%"
                isRequired
                isDisabled={isLoading}
                data-testid="telestionClientLoginForm"
            >
                <TextField
                    autoFocus={focused === 0}
                    onNext={() => setFocused(1)}
                    label="Backend Server"
                    initialValue={initialServerURL}
                    onChange={setServerUrl}
                    validator={isValidHttpUrl}
                    data-testid="telestionClientLoginForm-textField-serverUrl"
                />
                <TextField
                    autoFocus={focused === 1}
                    onNext={() => setFocused(2)}
                    label="Username"
                    initialValue={initialUsername}
                    onChange={setUsername}
                    validator={isValidText}
                    data-testid="telestionClientLoginForm-textField-username"
                />
                <TextField
                    autoFocus={focused === 2}
                    onNext={login}
                    label="Password"
                    type="password"
                    onChange={setPassword}
                    validator={isValidText}
                    data-testid="telestionClientLoginForm-textField-password"
                />
            </RSForm>

            <View marginTop="size-150">
                <LoginButton
                    isDisabled={!serverUrl || !username || !password}
                    isLoading={isLoading}
                    onPress={login}
                />
            </View>
        </>
    );
}