Приглашение в команду с валидацией
Сделай форму приглашения в команду: поле почты с подсказкой под ним, выбор роли из списка, переключатель «отправить уведомление» и кнопка отправки. Пока почта не похожа на адрес, поле показывает ошибку и кнопка заблокирована. После отправки над формой появляется сообщение об успехе, которое можно закрыть.
invite-form__none__claude-code__claude-opus-5__1 · 23.09.2026, 19:57:51 мск
Первый вызов модели получил 8 617 токенов входа, включая системный промпт Claude Code. Контекст до задачи — оценка по длине текста, для русского текста она занижает число токенов в полтора-два раза.
Компилятор
- Строка 3 · TS2724
'"@jinx-ui/react"' has no exported member named 'Alert'. Did you mean 'JxAlert'? - Строка 4 · TS2724
'"@jinx-ui/react"' has no exported member named 'Button'. Did you mean 'JxButton'? - Строка 5 · TS2305
Module '"@jinx-ui/react"' has no exported member 'Card'. - Строка 6 · TS2724
'"@jinx-ui/react"' has no exported member named 'Select'. Did you mean 'JxSelect'? - Строка 7 · TS2305
Module '"@jinx-ui/react"' has no exported member 'Stack'. - Строка 8 · TS2724
'"@jinx-ui/react"' has no exported member named 'Switch'. Did you mean 'JxSwitch'? - Строка 9 · TS2305
Module '"@jinx-ui/react"' has no exported member 'TextField'.
Линтер и покрытие
- inline-styleСтроки 50, 63Инлайновые стили вместо классов и токенов библиотеки
Ни одного: код написан без библиотеки, поэтому прогон не засчитан
Ожидались JxInputField, JxSelect, JxSwitch, JxAlert, JxButton · покрытие 0%
Только формулировка задачи
Вход 2 · выход 2 093 · из кэша 8 233 · в кэш 382 · 23 с
Рендер
Код компонента
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
import { useState, type ChangeEvent, type FormEvent } from 'react';
import {
Alert,
Button,
Card,
Select,
Stack,
Switch,
TextField,
} from '@jinx-ui/react';
type Role = 'viewer' | 'editor' | 'admin';
const ROLE_OPTIONS: Array<{ value: Role; label: string }> = [
{ value: 'viewer', label: 'Наблюдатель' },
{ value: 'editor', label: 'Редактор' },
{ value: 'admin', label: 'Администратор' },
];
const EMAIL_PATTERN = /^[^\s@]+@[^\s@]+\.[^\s@]{2,}$/;
export default function TeamInviteForm() {
const [email, setEmail] = useState('');
const [touched, setTouched] = useState(false);
const [role, setRole] = useState<Role>('viewer');
const [notify, setNotify] = useState(true);
const [invitedEmail, setInvitedEmail] = useState<string | null>(null);
const trimmedEmail = email.trim();
const isEmailValid = EMAIL_PATTERN.test(trimmedEmail);
const hasError = touched && !isEmailValid;
const handleEmailChange = (event: ChangeEvent<HTMLInputElement>) => {
setEmail(event.target.value);
};
const handleSubmit = (event: FormEvent<HTMLFormElement>) => {
event.preventDefault();
setTouched(true);
if (!isEmailValid) return;
setInvitedEmail(trimmedEmail);
setEmail('');
setTouched(false);
setRole('viewer');
};
return (
<Card className="jx-card">
<Stack direction="column" style={{ gap: 'var(--jx-space-4)' }}>
{invitedEmail && (
<Alert
variant="success"
title="Приглашение отправлено"
closable
onClose={() => setInvitedEmail(null)}
>
Мы пригласили {invitedEmail} в команду.
</Alert>
)}
<form onSubmit={handleSubmit} noValidate>
<Stack direction="column" style={{ gap: 'var(--jx-space-4)' }}>
<TextField
type="email"
name="email"
label="Почта участника"
placeholder="name@company.com"
value={email}
onChange={handleEmailChange}
onBlur={() => setTouched(true)}
invalid={hasError}
description="Пригласим по этому адресу, участник получит ссылку для входа."
errorText="Введите корректный адрес почты, например name@company.com."
autoComplete="email"
required
/>
<Select
name="role"
label="Роль в команде"
value={role}
onChange={(value: Role) => setRole(value)}
options={ROLE_OPTIONS}
/>
<Switch
name="notify"
label="Отправить уведомление"
description="Участник получит письмо сразу после приглашения."
checked={notify}
onChange={(event: ChangeEvent<HTMLInputElement>) =>
setNotify(event.target.checked)
}
/>
<Button type="submit" variant="primary" disabled={!isEmailValid}>
Отправить приглашение
</Button>
</Stack>
</form>
</Stack>
</Card>
);
}