diff --git a/components/DateFilter.js b/components/DateFilter.js index be83e634..25647db1 100644 --- a/components/DateFilter.js +++ b/components/DateFilter.js @@ -7,6 +7,9 @@ const filterOptions = [ { label: 'Last 7 days', value: '7day' }, { label: 'Last 30 days', value: '30day' }, { label: 'Last 90 days', value: '90day' }, + { label: 'Today', value: '1day' }, + { label: 'This week', value: '1week' }, + { label: 'This month', value: '1month' }, ]; export default function DateFilter({ value, onChange }) { diff --git a/components/DropDown.js b/components/DropDown.js index b3b08fdb..0f6d3362 100644 --- a/components/DropDown.js +++ b/components/DropDown.js @@ -9,13 +9,15 @@ export default function DropDown({ value, options = [], onChange }) { setShowMenu(state => !state); } - function handleSelect(value) { + function handleSelect(value, e) { + e.stopPropagation(); + setShowMenu(false); onChange(value); } useEffect(() => { function hideMenu(e) { - if (ref.current && !ref.current.contains(e.target)) { + if (!ref.current.contains(e.target)) { setShowMenu(false); } } diff --git a/components/Dropdown.module.css b/components/Dropdown.module.css index 7fe08fc1..f5a33baf 100644 --- a/components/Dropdown.module.css +++ b/components/Dropdown.module.css @@ -18,13 +18,13 @@ margin-top: 4px; border: 1px solid #b3b3b3; border-radius: 4px; + overflow: hidden; z-index: 1; } .option { background: #fff; padding: 4px 8px; - border-radius: 4px; cursor: pointer; } diff --git a/components/PageviewsChart.js b/components/PageviewsChart.js index 68d1cced..d3d6c444 100644 --- a/components/PageviewsChart.js +++ b/components/PageviewsChart.js @@ -14,7 +14,7 @@ export default function PageviewsChart({ data, unit, children }) { const n = data.pageviews.length; switch (unit) { case 'day': - if (n > 7) { + if (n >= 15) { return index % ~~(n / 15) === 0 ? format(d, 'MMM d') : ''; } return format(d, 'EEE M/d'); diff --git a/components/WebsiteChart.js b/components/WebsiteChart.js index 0aba3c9e..53430c69 100644 --- a/components/WebsiteChart.js +++ b/components/WebsiteChart.js @@ -10,7 +10,7 @@ import DateFilter from './DateFilter'; export default function WebsiteChart({ title, websiteId }) { const [data, setData] = useState(); const [dateRange, setDateRange] = useState(getDateRange('7day')); - const { startDate, endDate, unit } = dateRange; + const { startDate, endDate, unit, value } = dateRange; const [pageviews, uniques] = useMemo(() => { if (data) { @@ -46,10 +46,10 @@ export default function WebsiteChart({ title, websiteId }) {
{title}
- +
- + ); diff --git a/components/WebsiteList.js b/components/WebsiteList.js index 916f3fe6..225d462b 100644 --- a/components/WebsiteList.js +++ b/components/WebsiteList.js @@ -1,7 +1,6 @@ import React, { useState, useEffect } from 'react'; import { get } from 'lib/web'; import WebsiteChart from './WebsiteChart'; -import DateFilter from './DateFilter'; import styles from './WebsiteList.module.css'; export default function WebsiteList() { diff --git a/lib/date.js b/lib/date.js index f89d33a1..0ea3b4e0 100644 --- a/lib/date.js +++ b/lib/date.js @@ -7,10 +7,14 @@ import { subDays, startOfHour, startOfDay, + startOfWeek, + startOfMonth, endOfHour, endOfDay, + endOfWeek, + endOfMonth, differenceInHours, - differenceInDays, + differenceInCalendarDays, } from 'date-fns'; export function getTimezone() { @@ -23,23 +27,47 @@ export function getLocalTime(t) { export function getDateRange(value) { const now = new Date(); - const hour = endOfHour(now); - const day = endOfDay(now); - const { num, unit } = value.match(/^(?[0-9]+)(?hour|day)$/).groups; + const { num, unit } = value.match(/^(?[0-9]+)(?hour|day|week|month)$/).groups; + + if (+num === 1) { + switch (unit) { + case 'day': + return { + startDate: startOfDay(now), + endDate: endOfDay(now), + unit: 'hour', + value, + }; + case 'week': + return { + startDate: startOfWeek(now), + endDate: endOfWeek(now), + unit: 'day', + value, + }; + case 'month': + return { + startDate: startOfMonth(now), + endDate: endOfMonth(now), + unit: 'day', + value, + }; + } + } switch (unit) { case 'day': return { - startDate: subDays(day, num), - endDate: day, + startDate: subDays(startOfDay(now), num - 1), + endDate: endOfDay(now), unit, value, }; case 'hour': return { - startDate: subHours(hour, num), - endDate: hour, + startDate: subHours(startOfHour(now), num - 1), + endDate: endOfHour(now), unit, value, }; @@ -48,20 +76,22 @@ export function getDateRange(value) { const dateFuncs = { hour: [differenceInHours, addHours, startOfHour], - day: [differenceInDays, addDays, startOfDay], + day: [differenceInCalendarDays, addDays, startOfDay], }; export function getDateArray(data, startDate, endDate, unit) { const arr = []; const [diff, add, normalize] = dateFuncs[unit]; - const n = diff(endDate, startDate); + const n = diff(endDate, startDate) + 1; function findData(t) { - return data.find(e => getLocalTime(e.t).getTime() === normalize(t).getTime())?.y || 0; + const x = data.find(e => new Date(e.t).getTime() === normalize(new Date(t)).getTime()); + + return x?.y || 0; } for (let i = 0; i < n; i++) { - const t = add(startDate, i + 1); + const t = add(startDate, i); const y = findData(t); arr.push({ t, y }); diff --git a/lib/db.js b/lib/db.js index cd47cb92..8b3ae6d7 100644 --- a/lib/db.js +++ b/lib/db.js @@ -165,7 +165,7 @@ export async function getPageviewData( return runQuery( prisma.queryRaw( ` - select date_trunc('${unit}', created_at at time zone '${timezone}') t, + select date_trunc('${unit}', created_at at time zone '${timezone}') at time zone '${timezone}' t, count(${count}) y from pageview where website_id=$1