Выбор периода
Сделай выбор даты отчёта: календарь на месяц и над ним ряд быстрых вариантов «Сегодня», «Вчера», «Неделя назад», при нажатии на которые дата подставляется в календарь. Выбранная дата отдаётся наружу через колбэк onChange.
date-range__docs-rules__claude-code__claude-opus-5__1 · 23.09.2026, 21:55:59 мск
Проверки пройдены
Доки + правила · claude-opus-5 · Claude CodeКонтекст до задачи~23 785
Токенов на прогон50 324
Цена$0.291
Ошибок компилятора0
Первый вызов модели получил 49 054 токена входа, включая системный промпт Claude Code. Контекст до задачи — оценка по длине текста, для русского текста она занижает число токенов в полтора-два раза.
Компилятор
Ошибок нет: все компоненты и пропсы существуют.
Линтер и покрытие
- inline-styleСтроки 47, 51, 81Инлайновые стили вместо классов и токенов библиотеки
Компоненты библиотеки
JxCalendar, JxChip
Ожидались JxCalendar, JxChip · покрытие 100%
Доки (llms-full.txt, ~22548) · Правила (jinx-ui, ~1083)
Вход 2 · выход 1 270 · из кэша 8 233 · в кэш 40 819 · 14 с
Рендер
Код компонента
tsx93 строки
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
import { useCallback, useState } from 'react';
import { JxCalendar, JxChip } from '@jinx-ui/react';
interface ReportDatePickerProps {
value?: Date | null;
defaultValue?: Date | null;
onChange?: (value: Date | null) => void;
locale?: string;
}
const startOfDay = (date: Date): Date =>
new Date(date.getFullYear(), date.getMonth(), date.getDate());
const shiftDays = (days: number): Date => {
const base = startOfDay(new Date());
base.setDate(base.getDate() + days);
return base;
};
const presets: Array<{ id: string; label: string; offset: number }> = [
{ id: 'today', label: 'Сегодня', offset: 0 },
{ id: 'yesterday', label: 'Вчера', offset: -1 },
{ id: 'week-ago', label: 'Неделя назад', offset: -7 },
];
const isSameDay = (a: Date | null, b: Date | null): boolean =>
a != null && b != null && startOfDay(a).getTime() === startOfDay(b).getTime();
export default function ReportDatePicker({
value,
defaultValue = null,
onChange,
locale = 'ru-RU',
}: ReportDatePickerProps) {
const [internal, setInternal] = useState<Date | null>(defaultValue);
const selected = value !== undefined ? value : internal;
const select = useCallback(
(next: Date | null) => {
if (value === undefined) setInternal(next);
onChange?.(next);
},
[onChange, value],
);
return (
<div style={{ display: 'flex', flexDirection: 'column', gap: 12 }}>
<div
role="group"
aria-label="Быстрый выбор даты отчёта"
style={{ display: 'flex', flexWrap: 'wrap', gap: 8 }}
>
{presets.map((preset) => {
const presetDate = shiftDays(preset.offset);
const active = isSameDay(selected, presetDate);
return (
<JxChip
key={preset.id}
role="button"
tabIndex={0}
aria-pressed={active}
active={active}
onClick={() => select(shiftDays(preset.offset))}
onKeyDown={(event) => {
if (event.key === 'Enter' || event.key === ' ') {
event.preventDefault();
select(shiftDays(preset.offset));
}
}}
>
{preset.label}
</JxChip>
);
})}
</div>
<JxCalendar locale={locale} value={selected} onValueChange={select} />
<p
aria-live="polite"
style={{ margin: 0, color: 'var(--jx-text-2)', fontFamily: 'var(--jx-font-sans)' }}
>
{selected
? `Дата отчёта: ${selected.toLocaleDateString(locale, {
day: 'numeric',
month: 'long',
year: 'numeric',
})}`
: 'Дата не выбрана — нажмите вариант выше или день в календаре.'}
</p>
</div>
);
}