diff --git a/src/components/input/DateFilter.js b/src/components/input/DateFilter.js index ffbcff69..9fde27ca 100644 --- a/src/components/input/DateFilter.js +++ b/src/components/input/DateFilter.js @@ -13,6 +13,7 @@ export function DateFilter({ endDate, className, onChange, + selectedUnit, showAllTime = false, alignment = 'end', }) { @@ -66,7 +67,12 @@ export function DateFilter({ const renderValue = value => { return value.startsWith('range') ? ( - handleChange('custom')} /> + handleChange('custom')} + /> ) : ( options.find(e => e.value === value).label ); @@ -120,9 +126,11 @@ export function DateFilter({ ); } -const CustomRange = ({ startDate, endDate, onClick }) => { +const CustomRange = ({ startDate, endDate, selectedUnit, onClick }) => { const { locale } = useLocale(); + const monthFormat = +selectedUnit?.num === 1 && selectedUnit?.unit === 'month'; + function handleClick(e) { e.stopPropagation(); @@ -135,8 +143,14 @@ const CustomRange = ({ startDate, endDate, onClick }) => { - {formatDate(startDate, 'd LLL y', locale)} - {!isSameDay(startDate, endDate) && ` — ${formatDate(endDate, 'd LLL y', locale)}`} + {monthFormat ? ( + <>{formatDate(startDate, 'MMMM yyyy', locale)} + ) : ( + <> + {formatDate(startDate, 'd LLL y', locale)} + {!isSameDay(startDate, endDate) && ` — ${formatDate(endDate, 'd LLL y', locale)}`} + + )} ); diff --git a/src/components/input/WebsiteDateFilter.js b/src/components/input/WebsiteDateFilter.js index 2796b749..e56eba4f 100644 --- a/src/components/input/WebsiteDateFilter.js +++ b/src/components/input/WebsiteDateFilter.js @@ -1,24 +1,51 @@ import useDateRange from 'components/hooks/useDateRange'; +import { isAfter } from 'date-fns'; +import { incrementDateRange } from 'lib/date'; +import { Button, Flexbox, Icon, Icons } from 'react-basics'; import DateFilter from './DateFilter'; import styles from './WebsiteDateFilter.module.css'; export function WebsiteDateFilter({ websiteId }) { const [dateRange, setDateRange] = useDateRange(websiteId); - const { value, startDate, endDate } = dateRange; + const { value, startDate, endDate, selectedUnit } = dateRange; + + const isFutureDate = isAfter(incrementDateRange(dateRange, -1).startDate, new Date()); const handleChange = async value => { setDateRange(value); }; + const handleIncrement = async value => { + const newValue = incrementDateRange(dateRange, value); + + setDateRange(newValue); + }; + return ( - + <> + + + + + + + ); } diff --git a/src/components/pages/websites/WebsiteMetricsBar.js b/src/components/pages/websites/WebsiteMetricsBar.js index ad68a9fa..c625e239 100644 --- a/src/components/pages/websites/WebsiteMetricsBar.js +++ b/src/components/pages/websites/WebsiteMetricsBar.js @@ -110,8 +110,8 @@ export function WebsiteMetricsBar({ websiteId, sticky }) {
- +
diff --git a/src/lib/date.js b/src/lib/date.js index 49bff897..02f6053d 100644 --- a/src/lib/date.js +++ b/src/lib/date.js @@ -29,9 +29,19 @@ import { max, min, isDate, + subWeeks, } from 'date-fns'; import { getDateLocale } from 'lib/lang'; +export const TIME_UNIT = { + minute: 'minute', + hour: 'hour', + day: 'day', + week: 'week', + month: 'month', + year: 'year', +}; + const dateFuncs = { minute: [differenceInMinutes, addMinutes, startOfMinute], hour: [differenceInHours, addHours, startOfHour], @@ -81,6 +91,7 @@ export function parseDateRange(value, locale = 'en-US') { if (!match) return null; const { num, unit } = match.groups; + const selectedUnit = { num, unit }; if (+num === 1) { switch (unit) { @@ -90,6 +101,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: endOfDay(now), unit: 'hour', value, + selectedUnit, }; case 'week': return { @@ -97,6 +109,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: endOfWeek(now, { locale: dateLocale }), unit: 'day', value, + selectedUnit, }; case 'month': return { @@ -104,6 +117,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: endOfMonth(now), unit: 'day', value, + selectedUnit, }; case 'year': return { @@ -111,6 +125,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: endOfYear(now), unit: 'month', value, + selectedUnit, }; } } @@ -123,6 +138,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: subDays(endOfDay(now), 1), unit: 'hour', value, + selectedUnit, }; case 'week': return { @@ -130,6 +146,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: subDays(endOfWeek(now, { locale: dateLocale }), 1), unit: 'day', value, + selectedUnit, }; case 'month': return { @@ -137,6 +154,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: subMonths(endOfMonth(now), 1), unit: 'day', value, + selectedUnit, }; case 'year': return { @@ -144,6 +162,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: subYears(endOfYear(now), 1), unit: 'month', value, + selectedUnit, }; } } @@ -155,6 +174,7 @@ export function parseDateRange(value, locale = 'en-US') { endDate: endOfDay(now), unit, value, + selectedUnit, }; case 'hour': return { @@ -162,6 +182,46 @@ export function parseDateRange(value, locale = 'en-US') { endDate: endOfHour(now), unit, value, + selectedUnit, + }; + } +} + +export function incrementDateRange(value, increment) { + const { startDate, endDate, selectedUnit } = value; + + const { num, unit } = selectedUnit; + + const sub = num * increment; + + switch (unit) { + case 'day': + return { + ...value, + startDate: subDays(startDate, sub), + endDate: subDays(endDate, sub), + value: 'range', + }; + case 'week': + return { + ...value, + startDate: subWeeks(startDate, sub), + endDate: subWeeks(endDate, sub), + value: 'range', + }; + case 'month': + return { + ...value, + startDate: subMonths(startDate, sub), + endDate: subMonths(endDate, sub), + value: 'range', + }; + case 'year': + return { + ...value, + startDate: subYears(startDate, sub), + endDate: subYears(endDate, sub), + value: 'range', }; } } @@ -237,7 +297,7 @@ export function getDateLength(startDate, endDate, unit) { return diff(endDate, startDate) + 1; } -export const customFormats = { +export const CUSTOM_FORMATS = { 'en-US': { p: 'ha', pp: 'h:mm:ss', @@ -252,7 +312,7 @@ export const customFormats = { export function formatDate(date, str, locale = 'en-US') { return format( typeof date === 'string' ? new Date(date) : date, - customFormats?.[locale]?.[str] || str, + CUSTOM_FORMATS?.[locale]?.[str] || str, { locale: getDateLocale(locale), }, diff --git a/src/lib/types.ts b/src/lib/types.ts index 3f3839a4..e1e9da29 100644 --- a/src/lib/types.ts +++ b/src/lib/types.ts @@ -12,9 +12,12 @@ import { WEBSITE_FILTER_TYPES, } from './constants'; import * as yup from 'yup'; +import { TIME_UNIT } from './date'; type ObjectValues = T[keyof T]; +export type TimeUnit = ObjectValues; + export type CollectionType = ObjectValues; export type Role = ObjectValues; export type EventType = ObjectValues; @@ -181,6 +184,8 @@ export interface DateRange { startDate: Date; endDate: Date; value: string; + unit?: TimeUnit; + selectedUnit?: TimeUnit; } export interface QueryFilters { diff --git a/tsconfig.json b/tsconfig.json index 37457b40..78b225f4 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -20,7 +20,8 @@ "baseUrl": "./src", "strictNullChecks": false, "noEmit": true, - "jsx": "preserve" + "jsx": "preserve", + "incremental": true }, "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "exclude": ["node_modules"]