Пошаговая форма
Сделай трёхшаговую форму регистрации: шаги «Контакты», «Адрес», «Проверка». Сверху показывай индикатор текущего шага, снизу кнопки «Назад» и «Дальше», на последнем шаге кнопка «Отправить» вызывает переданный колбэк onSubmit.
wizard__readme__claude-code__claude-opus-5__1 · 23.09.2026, 20:05:16 мск
Есть проблемы
README · claude-opus-5 · Claude CodeКонтекст до задачи~798
Токенов на прогон13 188
Цена$0.103
Ошибок компилятора1
Первый вызов модели получил 9 541 токен входа, включая системный промпт Claude Code. Контекст до задачи — оценка по длине текста, для русского текста она занижает число токенов в полтора-два раза.
Компилятор
- Строка 2 · TS2305
Module '"@jinx-ui/react"' has no exported member 'JxInput'.
Выдуманные компоненты
JxInput
Линтер и покрытие
- inline-styleСтроки 52, 56, 68, 78, 95, 151, 155, 161, 162, 169Инлайновые стили вместо классов и токенов библиотеки
Компоненты библиотеки
JxButton, JxInput
Ожидались JxStepper, JxButton, JxInputField · покрытие 33%
README (README.md, ~644)
Вход 2 · выход 3 647 · из кэша 8 233 · в кэш 1 306 · 39 с
Рендер
Код компонента
tsx189 строк
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 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189
import { useState } from 'react';
import { JxButton, JxInput } from '@jinx-ui/react';
export type RegistrationData = {
name: string;
email: string;
phone: string;
country: string;
city: string;
street: string;
zip: string;
};
type RegistrationFormProps = {
onSubmit: (data: RegistrationData) => void;
};
const STEPS = ['Контакты', 'Адрес', 'Проверка'] as const;
const EMPTY: RegistrationData = {
name: '',
email: '',
phone: '',
country: '',
city: '',
street: '',
zip: '',
};
const REVIEW_FIELDS: Array<[keyof RegistrationData, string]> = [
['name', 'Имя'],
['email', 'Email'],
['phone', 'Телефон'],
['country', 'Страна'],
['city', 'Город'],
['street', 'Улица, дом'],
['zip', 'Индекс'],
];
export default function RegistrationForm({ onSubmit }: RegistrationFormProps) {
const [step, setStep] = useState(0);
const [data, setData] = useState<RegistrationData>(EMPTY);
const update = (key: keyof RegistrationData) => (value: string) =>
setData((prev) => ({ ...prev, [key]: value }));
const isLast = step === STEPS.length - 1;
return (
<section
aria-label="Регистрация"
style={{ display: 'grid', gap: 'var(--jx-space-6)' }}
>
<ol
aria-label="Шаги регистрации"
style={{
display: 'flex',
gap: 'var(--jx-space-4)',
listStyle: 'none',
margin: 0,
padding: 0,
}}
>
{STEPS.map((title, index) => (
<li
key={title}
aria-current={index === step ? 'step' : undefined}
style={{
display: 'flex',
alignItems: 'center',
gap: 'var(--jx-space-2)',
color:
index === step ? 'var(--jx-color-fg)' : 'var(--jx-color-fg-muted)',
}}
>
<span
aria-hidden="true"
style={{
display: 'inline-flex',
alignItems: 'center',
justifyContent: 'center',
width: 'var(--jx-space-6)',
height: 'var(--jx-space-6)',
borderRadius: 'var(--jx-radius-full)',
border: '1px solid currentColor',
}}
>
{index + 1}
</span>
<span>{title}</span>
</li>
))}
</ol>
<div style={{ display: 'grid', gap: 'var(--jx-space-4)' }}>
{step === 0 && (
<>
<JxInput
label="Имя"
value={data.name}
onValueChange={update('name')}
autoComplete="name"
/>
<JxInput
label="Email"
type="email"
value={data.email}
onValueChange={update('email')}
autoComplete="email"
/>
<JxInput
label="Телефон"
type="tel"
value={data.phone}
onValueChange={update('phone')}
autoComplete="tel"
/>
</>
)}
{step === 1 && (
<>
<JxInput
label="Страна"
value={data.country}
onValueChange={update('country')}
autoComplete="country-name"
/>
<JxInput
label="Город"
value={data.city}
onValueChange={update('city')}
autoComplete="address-level2"
/>
<JxInput
label="Улица, дом"
value={data.street}
onValueChange={update('street')}
autoComplete="street-address"
/>
<JxInput
label="Индекс"
value={data.zip}
onValueChange={update('zip')}
autoComplete="postal-code"
/>
</>
)}
{step === 2 && (
<dl style={{ display: 'grid', gap: 'var(--jx-space-3)', margin: 0 }}>
{REVIEW_FIELDS.map(([key, label]) => (
<div
key={key}
style={{
display: 'flex',
justifyContent: 'space-between',
gap: 'var(--jx-space-4)',
}}
>
<dt style={{ color: 'var(--jx-color-fg-muted)' }}>{label}</dt>
<dd style={{ margin: 0 }}>{data[key] || '—'}</dd>
</div>
))}
</dl>
)}
</div>
<div style={{ display: 'flex', gap: 'var(--jx-space-3)' }}>
<JxButton
variant="secondary"
disabled={step === 0}
onClick={() => setStep((prev) => prev - 1)}
>
Назад
</JxButton>
{isLast ? (
<JxButton variant="primary" onClick={() => onSubmit(data)}>
Отправить
</JxButton>
) : (
<JxButton variant="primary" onClick={() => setStep((prev) => prev + 1)}>
Дальше
</JxButton>
)}
</div>
</section>
);
}