Выбор периода

Сделай выбор даты отчёта: календарь на месяц и над ним ряд быстрых вариантов «Сегодня», «Вчера», «Неделя назад», при нажатии на которые дата подставляется в календарь. Выбранная дата отдаётся наружу через колбэк onChange.

date-range__mcp__claude-code__claude-opus-5__1 · 24.09.2026, 13:30:20 мск

Проверки пройдены
MCP · claude-opus-5 · Claude Code
Контекст до задачи~2 405
Токенов на прогон30 265
Цена$0.076
Ошибок компилятора0

Первый вызов модели получил 12 483 токена входа, включая системный промпт Claude Code; вызовов модели 2, каждый отправлял разговор заново, и самый большой получил 16 315 токенов. Контекст до задачи — оценка по длине текста, для русского текста она занижает число токенов в полтора-два раза.

Компилятор

Ошибок нет: все компоненты и пропсы существуют.

Линтер и покрытие

  • inline-styleСтроки 43, 44, 71
    Инлайновые стили вместо классов и токенов библиотеки
Компоненты библиотеки

JxCalendar, JxChip

Ожидались JxCalendar, JxChip · покрытие 100%

Вызовы инструментов · 3
  1. get_rules({"task":"ui"}) → ~1247 токенов
  2. get_component_api({"name":"JxCalendar","detail":"full"}) → ~516 токенов
  3. get_component_api({"name":"JxChip","detail":"full"}) → ~360 токенов
Контекст

Инструменты (search_components,get_component_api,get_component_examples,list_design_tokens,get_docs,get_rules, ~1213)

Вход 4 · выход 1 467 · из кэша 24 496 · в кэш 4 298 · 16 с

Рендер

Код компонента

tsx85 строк
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
import { useCallback, useState } from 'react';
import { JxCalendar, JxChip } from '@jinx-ui/react';

type ReportDatePickerProps = {
  value?: Date | null;
  defaultValue?: Date | null;
  onChange?: (value: Date | null) => void;
};

const DAY_MS = 24 * 60 * 60 * 1000;

function startOfDay(date: Date): Date {
  return new Date(date.getFullYear(), date.getMonth(), date.getDate());
}

function shiftDays(days: number): Date {
  return startOfDay(new Date(Date.now() - days * DAY_MS));
}

const presets: { id: string; label: string; resolve: () => Date }[] = [
  { id: 'today', label: 'Сегодня', resolve: () => shiftDays(0) },
  { id: 'yesterday', label: 'Вчера', resolve: () => shiftDays(1) },
  { id: 'week-ago', label: 'Неделя назад', resolve: () => shiftDays(7) },
];

function isSameDay(a: Date | null | undefined, b: Date): boolean {
  return !!a && startOfDay(a).getTime() === b.getTime();
}

export default function ReportDatePicker({ value, defaultValue = null, onChange }: ReportDatePickerProps) {
  const [internal, setInternal] = useState<Date | null>(defaultValue);
  const current = value !== undefined ? value : internal;

  const commit = useCallback(
    (next: Date | null) => {
      if (value === undefined) setInternal(next);
      onChange?.(next);
    },
    [onChange, value],
  );

  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: '12px', maxWidth: '320px' }}>
      <div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px' }} role="group" aria-label="Быстрый выбор даты отчёта">
        {presets.map((preset) => {
          const presetDate = preset.resolve();
          return (
            <JxChip
              key={preset.id}
              role="button"
              tabIndex={0}
              aria-pressed={isSameDay(current, presetDate)}
              active={isSameDay(current, presetDate)}
              onClick={() => commit(presetDate)}
              onKeyDown={(event) => {
                if (event.key === 'Enter' || event.key === ' ') {
                  event.preventDefault();
                  commit(presetDate);
                }
              }}
            >
              {preset.label}
            </JxChip>
          );
        })}
      </div>

      <JxCalendar locale="ru-RU" value={current} onValueChange={commit} aria-label="Дата отчёта" />

      <p
        style={{
          margin: 0,
          font: 'inherit',
          fontFamily: 'var(--jx-font-sans)',
          color: current ? 'var(--jx-text)' : 'var(--jx-text-2)',
        }}
        aria-live="polite"
      >
        {current
          ? `Отчёт за ${current.toLocaleDateString('ru-RU', { day: 'numeric', month: 'long', year: 'numeric' })}`
          : 'Дата не выбрана — выберите день в календаре или быстрый вариант выше.'}
      </p>
    </div>
  );
}