Merge remote-tracking branch 'origin/dev' into dev

This commit is contained in:
Mike Cao 2023-08-21 19:32:32 -07:00
commit 56ee52e349
6 changed files with 124 additions and 17 deletions

View File

@ -13,6 +13,7 @@ export function DateFilter({
endDate, endDate,
className, className,
onChange, onChange,
selectedUnit,
showAllTime = false, showAllTime = false,
alignment = 'end', alignment = 'end',
}) { }) {
@ -66,7 +67,12 @@ export function DateFilter({
const renderValue = value => { const renderValue = value => {
return value.startsWith('range') ? ( return value.startsWith('range') ? (
<CustomRange startDate={startDate} endDate={endDate} onClick={() => handleChange('custom')} /> <CustomRange
startDate={startDate}
endDate={endDate}
selectedUnit={selectedUnit}
onClick={() => handleChange('custom')}
/>
) : ( ) : (
options.find(e => e.value === value).label 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 { locale } = useLocale();
const monthFormat = +selectedUnit?.num === 1 && selectedUnit?.unit === 'month';
function handleClick(e) { function handleClick(e) {
e.stopPropagation(); e.stopPropagation();
@ -135,8 +143,14 @@ const CustomRange = ({ startDate, endDate, onClick }) => {
<Icons.Calendar /> <Icons.Calendar />
</Icon> </Icon>
<Text> <Text>
{formatDate(startDate, 'd LLL y', locale)} {monthFormat ? (
{!isSameDay(startDate, endDate) && `${formatDate(endDate, 'd LLL y', locale)}`} <>{formatDate(startDate, 'MMMM yyyy', locale)}</>
) : (
<>
{formatDate(startDate, 'd LLL y', locale)}
{!isSameDay(startDate, endDate) && `${formatDate(endDate, 'd LLL y', locale)}`}
</>
)}
</Text> </Text>
</Flexbox> </Flexbox>
); );

View File

@ -1,24 +1,51 @@
import useDateRange from 'components/hooks/useDateRange'; 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 DateFilter from './DateFilter';
import styles from './WebsiteDateFilter.module.css'; import styles from './WebsiteDateFilter.module.css';
export function WebsiteDateFilter({ websiteId }) { export function WebsiteDateFilter({ websiteId }) {
const [dateRange, setDateRange] = useDateRange(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 => { const handleChange = async value => {
setDateRange(value); setDateRange(value);
}; };
const handleIncrement = async value => {
const newValue = incrementDateRange(dateRange, value);
setDateRange(newValue);
};
return ( return (
<DateFilter <>
className={styles.dropdown} <DateFilter
value={value} className={styles.dropdown}
startDate={startDate} value={value}
endDate={endDate} startDate={startDate}
onChange={handleChange} endDate={endDate}
showAllTime={true} selectedUnit={selectedUnit}
/> onChange={handleChange}
showAllTime={true}
/>
<Flexbox justifyContent="center" gap={10} className={styles.container}>
<Button onClick={() => handleIncrement(1)}>
<Icon rotate={90}>
<Icons.ChevronDown />
</Icon>
</Button>
<Button onClick={() => handleIncrement(-1)} disabled={isFutureDate}>
<Icon rotate={270}>
<Icons.ChevronDown />
</Icon>
</Button>
</Flexbox>
</>
); );
} }

View File

@ -110,8 +110,8 @@ export function WebsiteMetricsBar({ websiteId, sticky }) {
</Column> </Column>
<Column defaultSize={12} xl={4}> <Column defaultSize={12} xl={4}>
<div className={styles.actions}> <div className={styles.actions}>
<RefreshButton websiteId={websiteId} />
<WebsiteDateFilter websiteId={websiteId} /> <WebsiteDateFilter websiteId={websiteId} />
<RefreshButton websiteId={websiteId} />
</div> </div>
</Column> </Column>
</Row> </Row>

View File

@ -29,9 +29,19 @@ import {
max, max,
min, min,
isDate, isDate,
subWeeks,
} from 'date-fns'; } from 'date-fns';
import { getDateLocale } from 'lib/lang'; import { getDateLocale } from 'lib/lang';
export const TIME_UNIT = {
minute: 'minute',
hour: 'hour',
day: 'day',
week: 'week',
month: 'month',
year: 'year',
};
const dateFuncs = { const dateFuncs = {
minute: [differenceInMinutes, addMinutes, startOfMinute], minute: [differenceInMinutes, addMinutes, startOfMinute],
hour: [differenceInHours, addHours, startOfHour], hour: [differenceInHours, addHours, startOfHour],
@ -81,6 +91,7 @@ export function parseDateRange(value, locale = 'en-US') {
if (!match) return null; if (!match) return null;
const { num, unit } = match.groups; const { num, unit } = match.groups;
const selectedUnit = { num, unit };
if (+num === 1) { if (+num === 1) {
switch (unit) { switch (unit) {
@ -90,6 +101,7 @@ export function parseDateRange(value, locale = 'en-US') {
endDate: endOfDay(now), endDate: endOfDay(now),
unit: 'hour', unit: 'hour',
value, value,
selectedUnit,
}; };
case 'week': case 'week':
return { return {
@ -97,6 +109,7 @@ export function parseDateRange(value, locale = 'en-US') {
endDate: endOfWeek(now, { locale: dateLocale }), endDate: endOfWeek(now, { locale: dateLocale }),
unit: 'day', unit: 'day',
value, value,
selectedUnit,
}; };
case 'month': case 'month':
return { return {
@ -104,6 +117,7 @@ export function parseDateRange(value, locale = 'en-US') {
endDate: endOfMonth(now), endDate: endOfMonth(now),
unit: 'day', unit: 'day',
value, value,
selectedUnit,
}; };
case 'year': case 'year':
return { return {
@ -111,6 +125,7 @@ export function parseDateRange(value, locale = 'en-US') {
endDate: endOfYear(now), endDate: endOfYear(now),
unit: 'month', unit: 'month',
value, value,
selectedUnit,
}; };
} }
} }
@ -123,6 +138,7 @@ export function parseDateRange(value, locale = 'en-US') {
endDate: subDays(endOfDay(now), 1), endDate: subDays(endOfDay(now), 1),
unit: 'hour', unit: 'hour',
value, value,
selectedUnit,
}; };
case 'week': case 'week':
return { return {
@ -130,6 +146,7 @@ export function parseDateRange(value, locale = 'en-US') {
endDate: subDays(endOfWeek(now, { locale: dateLocale }), 1), endDate: subDays(endOfWeek(now, { locale: dateLocale }), 1),
unit: 'day', unit: 'day',
value, value,
selectedUnit,
}; };
case 'month': case 'month':
return { return {
@ -137,6 +154,7 @@ export function parseDateRange(value, locale = 'en-US') {
endDate: subMonths(endOfMonth(now), 1), endDate: subMonths(endOfMonth(now), 1),
unit: 'day', unit: 'day',
value, value,
selectedUnit,
}; };
case 'year': case 'year':
return { return {
@ -144,6 +162,7 @@ export function parseDateRange(value, locale = 'en-US') {
endDate: subYears(endOfYear(now), 1), endDate: subYears(endOfYear(now), 1),
unit: 'month', unit: 'month',
value, value,
selectedUnit,
}; };
} }
} }
@ -155,6 +174,7 @@ export function parseDateRange(value, locale = 'en-US') {
endDate: endOfDay(now), endDate: endOfDay(now),
unit, unit,
value, value,
selectedUnit,
}; };
case 'hour': case 'hour':
return { return {
@ -162,6 +182,46 @@ export function parseDateRange(value, locale = 'en-US') {
endDate: endOfHour(now), endDate: endOfHour(now),
unit, unit,
value, 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; return diff(endDate, startDate) + 1;
} }
export const customFormats = { export const CUSTOM_FORMATS = {
'en-US': { 'en-US': {
p: 'ha', p: 'ha',
pp: 'h:mm:ss', pp: 'h:mm:ss',
@ -252,7 +312,7 @@ export const customFormats = {
export function formatDate(date, str, locale = 'en-US') { export function formatDate(date, str, locale = 'en-US') {
return format( return format(
typeof date === 'string' ? new Date(date) : date, typeof date === 'string' ? new Date(date) : date,
customFormats?.[locale]?.[str] || str, CUSTOM_FORMATS?.[locale]?.[str] || str,
{ {
locale: getDateLocale(locale), locale: getDateLocale(locale),
}, },

View File

@ -12,9 +12,12 @@ import {
WEBSITE_FILTER_TYPES, WEBSITE_FILTER_TYPES,
} from './constants'; } from './constants';
import * as yup from 'yup'; import * as yup from 'yup';
import { TIME_UNIT } from './date';
type ObjectValues<T> = T[keyof T]; type ObjectValues<T> = T[keyof T];
export type TimeUnit = ObjectValues<typeof TIME_UNIT>;
export type CollectionType = ObjectValues<typeof COLLECTION_TYPE>; export type CollectionType = ObjectValues<typeof COLLECTION_TYPE>;
export type Role = ObjectValues<typeof ROLES>; export type Role = ObjectValues<typeof ROLES>;
export type EventType = ObjectValues<typeof EVENT_TYPE>; export type EventType = ObjectValues<typeof EVENT_TYPE>;
@ -181,6 +184,8 @@ export interface DateRange {
startDate: Date; startDate: Date;
endDate: Date; endDate: Date;
value: string; value: string;
unit?: TimeUnit;
selectedUnit?: TimeUnit;
} }
export interface QueryFilters { export interface QueryFilters {

View File

@ -20,7 +20,8 @@
"baseUrl": "./src", "baseUrl": "./src",
"strictNullChecks": false, "strictNullChecks": false,
"noEmit": true, "noEmit": true,
"jsx": "preserve" "jsx": "preserve",
"incremental": true
}, },
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"], "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx"],
"exclude": ["node_modules"] "exclude": ["node_modules"]