Пошаговая форма

Сделай трёхшаговую форму регистрации: шаги «Контакты», «Адрес», «Проверка». Сверху показывай индикатор текущего шага, снизу кнопки «Назад» и «Дальше», на последнем шаге кнопка «Отправить» вызывает переданный колбэк 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>
  );
}