Initial commit
This commit is contained in:
97
src/features/store-admin/DateRangePicker.tsx
Normal file
97
src/features/store-admin/DateRangePicker.tsx
Normal file
@@ -0,0 +1,97 @@
|
||||
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>
|
||||
);
|
||||
}
|
||||
Reference in New Issue
Block a user