Files
daily_console_web/src/features/store-admin/DateRangePicker.tsx
2026-08-24 20:35:18 +05:30

98 lines
3.9 KiB
TypeScript

import { useMemo } from 'react';
import { DateRangeInput, type DateRange as AstryxDateRange, type ISODateString } from '@astryxdesign/core';
import type { DateRange } from '@/api/insights';
export type RangePreset = 'today' | 'yesterday' | 'week' | 'month' | 'custom';
/** `YYYY-MM-DD` in LOCAL time — `toISOString()` would shift a shop in IST back a day. */
export function isoDay(date: Date): string {
const year = date.getFullYear();
const month = String(date.getMonth() + 1).padStart(2, '0');
const day = String(date.getDate()).padStart(2, '0');
return `${year}-${month}-${day}`;
}
export function presetRange(preset: RangePreset, now = new Date()): DateRange {
const today = new Date(now.getFullYear(), now.getMonth(), now.getDate());
switch (preset) {
case 'today':
return { fromdate: isoDay(today), todate: isoDay(today) };
case 'yesterday': {
const yesterday = new Date(today);
yesterday.setDate(today.getDate() - 1);
return { fromdate: isoDay(yesterday), todate: isoDay(yesterday) };
}
case 'week': {
// Monday-first. A retail week that starts on Sunday makes Monday's
// takings the previous week's, which is not how anyone here counts.
const weekday = (today.getDay() + 6) % 7;
const monday = new Date(today);
monday.setDate(today.getDate() - weekday);
return { fromdate: isoDay(monday), todate: isoDay(today) };
}
case 'month': {
const first = new Date(today.getFullYear(), today.getMonth(), 1);
return { fromdate: isoDay(first), todate: isoDay(today) };
}
case 'custom':
return {};
}
}
export interface DateRangePickerProps {
preset: RangePreset;
range: DateRange;
onChange: (preset: RangePreset, range: DateRange) => void;
}
export function DateRangePicker({ range, onChange }: DateRangePickerProps) {
const astryxRange = useMemo<AstryxDateRange | null>(() => {
if (range.fromdate && range.todate) {
return { start: range.fromdate as ISODateString, end: range.todate as ISODateString };
}
return null;
}, [range]);
const presets = useMemo(() => {
return [
{ label: 'Today', getRange: () => { const r = presetRange('today'); return { start: r.fromdate as ISODateString, end: r.todate as ISODateString }; } },
{ label: 'Yesterday', getRange: () => { const r = presetRange('yesterday'); return { start: r.fromdate as ISODateString, end: r.todate as ISODateString }; } },
{ label: 'This week', getRange: () => { const r = presetRange('week'); return { start: r.fromdate as ISODateString, end: r.todate as ISODateString }; } },
{ label: 'This month', getRange: () => { const r = presetRange('month'); return { start: r.fromdate as ISODateString, end: r.todate as ISODateString }; } },
];
}, []);
return (
<div style={{ width: 180 }}>
<DateRangeInput
width={180}
size="sm"
label="Date range"
isLabelHidden
value={astryxRange}
presets={presets}
onChange={(newRange) => {
if (!newRange) {
onChange('custom', {});
return;
}
// Determine if the new range matches a preset
const today = presetRange('today');
const yesterday = presetRange('yesterday');
const week = presetRange('week');
const month = presetRange('month');
let matchedPreset: RangePreset = 'custom';
if (newRange.start === today.fromdate && newRange.end === today.todate) matchedPreset = 'today';
else if (newRange.start === yesterday.fromdate && newRange.end === yesterday.todate) matchedPreset = 'yesterday';
else if (newRange.start === week.fromdate && newRange.end === week.todate) matchedPreset = 'week';
else if (newRange.start === month.fromdate && newRange.end === month.todate) matchedPreset = 'month';
onChange(matchedPreset, { fromdate: newRange.start, todate: newRange.end });
}}
/>
</div>
);
}