aaaff0705b
* refactor(data-table): clean up DateRangeFilter range options - Replace 'past' | 'custom' with 'past' | 'future' | 'any' | 'customOnly' - Add direction field to PresetOption for preset compatibility filtering - Derive presets visibility automatically based on compatible presets - Update bookings list to use new range values: - past -> 'past' - upcoming -> 'future' - unconfirmed/recurring/cancelled -> 'any' Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * feat(playground): add DateRangeFilter playground page with E2E tests - Add playground page at /settings/admin/playground/date-range-filter - Demonstrate all 4 range options: past, future, any, customOnly - Add link to playground index page - Add E2E tests for presets visibility and date restrictions Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * fix(playground): use correct meta.filter pattern for column filter config Co-Authored-By: eunjae@cal.com <hey@eunjae.dev> * clean up the playground esign * add unit tests instead of e2e * fix the implementation --------- Co-authored-by: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com>
108 lines
3.1 KiB
TypeScript
108 lines
3.1 KiB
TypeScript
import dayjs from "@calcom/dayjs";
|
|
|
|
import { ColumnFilterType, type DateRangeFilterValue } from "./types";
|
|
|
|
export type PresetOptionValue = "c" | "w" | "m" | "y" | "t" | "tdy";
|
|
|
|
export type PresetDirection = "past" | "future" | "any";
|
|
|
|
export type PresetOption = {
|
|
labelKey: string;
|
|
i18nOptions?: Record<string, string | number>;
|
|
value: PresetOptionValue;
|
|
direction: PresetDirection;
|
|
};
|
|
|
|
export const CUSTOM_PRESET_VALUE = "c" as const;
|
|
|
|
export const DEFAULT_PRESET: PresetOption = {
|
|
labelKey: "last_number_of_days",
|
|
i18nOptions: { count: 7 },
|
|
value: "w",
|
|
direction: "past",
|
|
};
|
|
export const CUSTOM_PRESET: PresetOption = {
|
|
labelKey: "custom_range",
|
|
value: CUSTOM_PRESET_VALUE,
|
|
direction: "any",
|
|
};
|
|
|
|
export const PRESET_OPTIONS: PresetOption[] = [
|
|
{ labelKey: "today", value: "tdy", direction: "past" },
|
|
DEFAULT_PRESET,
|
|
{ labelKey: "last_number_of_days", i18nOptions: { count: 30 }, value: "t", direction: "past" },
|
|
{ labelKey: "month_to_date", value: "m", direction: "past" },
|
|
{ labelKey: "year_to_date", value: "y", direction: "past" },
|
|
CUSTOM_PRESET,
|
|
];
|
|
|
|
export const getCompatiblePresets = (range: "past" | "future" | "any" | "customOnly"): PresetOption[] => {
|
|
if (range === "customOnly") {
|
|
return [];
|
|
}
|
|
return PRESET_OPTIONS.filter((preset) => {
|
|
if (preset.direction === "any") return true;
|
|
if (range === "any") return true;
|
|
return preset.direction === range;
|
|
});
|
|
};
|
|
|
|
export const getDefaultStartDate = () => dayjs().subtract(6, "day").startOf("day");
|
|
|
|
export const getDefaultEndDate = () => dayjs().endOf("day");
|
|
|
|
export const getDateRangeFromPreset = (val: string | null) => {
|
|
let startDate;
|
|
let endDate;
|
|
const preset = PRESET_OPTIONS.find((o) => o.value === val);
|
|
if (!preset) {
|
|
return { startDate: getDefaultStartDate(), endDate: getDefaultEndDate(), preset: CUSTOM_PRESET };
|
|
}
|
|
|
|
switch (val) {
|
|
case "tdy": // Today
|
|
startDate = dayjs().startOf("day");
|
|
endDate = dayjs().endOf("day");
|
|
break;
|
|
case "w": // Last 7 days
|
|
startDate = dayjs().subtract(6, "day").startOf("day");
|
|
endDate = dayjs().endOf("day");
|
|
break;
|
|
case "t": // Last 30 days
|
|
startDate = dayjs().subtract(29, "day").startOf("day");
|
|
endDate = dayjs().endOf("day");
|
|
break;
|
|
case "m": // Month to Date
|
|
startDate = dayjs().startOf("month");
|
|
endDate = dayjs().endOf("day");
|
|
break;
|
|
case "y": // Year to Date
|
|
startDate = dayjs().startOf("year");
|
|
endDate = dayjs().endOf("day");
|
|
break;
|
|
default:
|
|
throw new Error(`Invalid preset value: ${val}`);
|
|
}
|
|
|
|
return { startDate, endDate, preset };
|
|
};
|
|
|
|
export const recalculateDateRange = (filterValue: DateRangeFilterValue): DateRangeFilterValue => {
|
|
// If it's a custom range, return as is
|
|
if (filterValue.data.preset === CUSTOM_PRESET_VALUE) {
|
|
return filterValue;
|
|
}
|
|
|
|
// Recalculate dates based on the current timestamp
|
|
const { startDate, endDate } = getDateRangeFromPreset(filterValue.data.preset);
|
|
|
|
return {
|
|
type: ColumnFilterType.DATE_RANGE,
|
|
data: {
|
|
...filterValue.data,
|
|
startDate: startDate.toISOString(),
|
|
endDate: endDate.toISOString(),
|
|
},
|
|
};
|
|
};
|