// Custom date-range picker. The two native (#date-start /
// #date-end) stay in the DOM (hidden) as the source of truth — all filter code
// keeps reading/writing them. The calendar selects into a temporary state; the
// filter is applied (and the popup closed) only when the user presses «Применить».
// Both endpoints are chosen by clicking days; «Сбросить» clears the in-progress
// selection.
const MONTHS = ['Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь'];
const WEEKDAYS = ['пн', 'вт', 'ср', 'чт', 'пт', 'сб', 'вс'];
function parseISO(iso: string): Date | null {
return iso ? new Date(iso + 'T00:00:00') : null;
}
function toISO(d: Date): string {
return `${d.getFullYear()}-${String(d.getMonth() + 1).padStart(2, '0')}-${String(d.getDate()).padStart(2, '0')}`;
}
function fmt(iso: string): string {
const p = iso.split('-');
// Short 2-digit year so the full range fits the compact "Период" field.
return p.length === 3 ? `${p[2]}.${p[1]}.${p[0].slice(2)}` : iso;
}
export interface DateRange {
/** Refresh the field text (+ open calendar) from the hidden inputs. */
sync(): void;
}
export function createDateRange(): DateRange {
const startInput = document.getElementById('date-start') as HTMLInputElement;
const endInput = document.getElementById('date-end') as HTMLInputElement;
const field = document.getElementById('dr-field') as HTMLElement;
const text = document.getElementById('dr-text') as HTMLElement;
const clearBtn = document.getElementById('dr-clear') as HTMLElement;
const cal = document.getElementById('dr-cal') as HTMLElement;
let viewY = new Date().getFullYear();
let viewM = new Date().getMonth();
// In-progress selection (committed to the inputs only when both ends are set).
let selStart = '';
let selEnd = '';
function updateText(): void {
const s = startInput.value;
const e = endInput.value;
if (s && e) text.textContent = `${fmt(s)} — ${fmt(e)}`;
else if (s) text.textContent = `с ${fmt(s)}`;
else if (e) text.textContent = `по ${fmt(e)}`;
else text.textContent = 'Период';
clearBtn.style.display = s || e ? '' : 'none';
field.classList.toggle('has-value', !!(s || e));
}
function render(): void {
const s = parseISO(selStart);
const e = parseISO(selEnd);
const parts: string[] = [
`
` +
`${MONTHS[viewM]} ${viewY}` +
`
`,
'
',
];
for (const w of WEEKDAYS) parts.push(`${w}`);
const lead = (new Date(viewY, viewM, 1).getDay() + 6) % 7; // Monday-first
const days = new Date(viewY, viewM + 1, 0).getDate();
for (let i = 0; i < lead; i++) parts.push('');
for (let d = 1; d <= days; d++) {
const cur = new Date(viewY, viewM, d);
const iso = toISO(cur);
let cls = 'dr-day';
if (iso === selStart) cls += ' s';
if (iso === selEnd) cls += ' e';
if (s && e && cur > s && cur < e) cls += ' rng';
parts.push(``);
}
parts.push('