Add quick filter buttons.

This commit is contained in:
Mike Cao 2020-07-30 01:08:21 -07:00
parent 9beec1b50e
commit ff4492ffb5
10 changed files with 80 additions and 25 deletions

View File

@ -1,4 +1,4 @@
import React, { useState } from 'react'; import React from 'react';
import { useSpring, animated } from 'react-spring'; import { useSpring, animated } from 'react-spring';
import styles from './MetricCard.module.css'; import styles from './MetricCard.module.css';

View File

@ -8,6 +8,7 @@
.value { .value {
font-size: 36px; font-size: 36px;
line-height: 40px; line-height: 40px;
min-height: 40px;
font-weight: 600; font-weight: 600;
} }

View File

@ -19,6 +19,7 @@
width: 150px; width: 150px;
height: 50px; height: 50px;
transform: translate(-50%, -60px); transform: translate(-50%, -60px);
backdrop-filter: blur(4px);
} }
.content:after { .content:after {
@ -52,5 +53,5 @@
height: 10px; height: 10px;
border-radius: 100%; border-radius: 100%;
border: 1px solid #fff; border: 1px solid #fff;
margin-right: 10px; margin-right: 8px;
} }

View File

@ -0,0 +1,33 @@
import React, { useState } from 'react';
import classNames from 'classnames';
import { getDateRange } from 'lib/date';
import styles from './QuickButtons.module.css';
const options = {
'24hour': '24h',
'7day': '7d',
'30day': '30d',
};
export default function QuickButtons({ onChange }) {
const [active, setActive] = useState('7day');
function handleClick(value) {
setActive(value);
onChange(getDateRange(value));
}
return (
<div className={styles.buttons}>
{Object.keys(options).map(key => (
<div
key={key}
className={classNames(styles.button, { [styles.active]: active === key })}
onClick={() => handleClick(key)}
>
{options[key]}
</div>
))}
</div>
);
}

View File

@ -0,0 +1,20 @@
.buttons {
display: flex;
}
.button {
font-size: 12px;
background: #f5f5f5;
padding: 4px 8px;
border-radius: 4px;
margin-right: 10px;
cursor: pointer;
}
.button:hover {
background: #eaeaea;
}
.active {
font-weight: 600;
}

View File

@ -2,39 +2,24 @@ import React, { useState, useEffect } from 'react';
import { get } from 'lib/web'; import { get } from 'lib/web';
import WebsiteStats from './WebsiteStats'; import WebsiteStats from './WebsiteStats';
import DateFilter from './DateFilter'; import DateFilter from './DateFilter';
import { getDateRange } from 'lib/date';
import styles from './WebsiteList.module.css'; import styles from './WebsiteList.module.css';
export default function WebsiteList() { export default function WebsiteList() {
const [data, setData] = useState(); const [data, setData] = useState();
const [dateRange, setDateRange] = useState(getDateRange('7day'));
const { startDate, endDate, unit } = dateRange;
async function loadData() { async function loadData() {
setData(await get(`/api/website`)); setData(await get(`/api/website`));
} }
function handleDateChange(value) {
setDateRange(value);
}
useEffect(() => { useEffect(() => {
loadData(); loadData();
}, []); }, []);
return ( return (
<div className={styles.container}> <div className={styles.container}>
<DateFilter onChange={handleDateChange} />
{data && {data &&
data.websites.map(({ website_id, label }) => ( data.websites.map(({ website_id, label }) => (
<WebsiteStats <WebsiteStats key={website_id} title={label} websiteId={website_id} />
key={website_id}
title={label}
websiteId={website_id}
startDate={startDate}
endDate={endDate}
unit={unit}
/>
))} ))}
</div> </div>
); );

View File

@ -1,12 +1,16 @@
import React, { useState, useEffect, useMemo } from 'react'; import React, { useState, useEffect, useMemo } from 'react';
import PageviewsChart from './PageviewsChart'; import PageviewsChart from './PageviewsChart';
import { get } from 'lib/web'; import { get } from 'lib/web';
import { getDateArray, getTimezone } from 'lib/date'; import { getDateArray, getDateRange, getTimezone } from 'lib/date';
import WebsiteSummary from './WebsiteSummary'; import WebsiteSummary from './WebsiteSummary';
import QuickButtons from './QuickButtons';
import styles from './WebsiteStats.module.css'; import styles from './WebsiteStats.module.css';
export default function WebsiteStats({ title, websiteId, startDate, endDate, unit }) { export default function WebsiteStats({ title, websiteId }) {
const [data, setData] = useState(); const [data, setData] = useState();
const [dateRange, setDateRange] = useState(getDateRange('7day'));
const { startDate, endDate, unit } = dateRange;
const [pageviews, uniques] = useMemo(() => { const [pageviews, uniques] = useMemo(() => {
if (data) { if (data) {
return [ return [
@ -17,6 +21,10 @@ export default function WebsiteStats({ title, websiteId, startDate, endDate, uni
return [[], []]; return [[], []];
}, [data]); }, [data]);
function handleDateChange(values) {
setDateRange(values);
}
async function loadData() { async function loadData() {
setData( setData(
await get(`/api/website/${websiteId}/pageviews`, { await get(`/api/website/${websiteId}/pageviews`, {
@ -35,7 +43,10 @@ export default function WebsiteStats({ title, websiteId, startDate, endDate, uni
return ( return (
<div className={styles.container}> <div className={styles.container}>
<div className={styles.title}>{title}</div> <div className={styles.title}>{title}</div>
<WebsiteSummary websiteId={websiteId} startDate={startDate} endDate={endDate} /> <div className={styles.header}>
<WebsiteSummary websiteId={websiteId} startDate={startDate} endDate={endDate} />
<QuickButtons onChange={handleDateChange} />
</div>
<PageviewsChart data={{ pageviews, uniques }} unit={unit} /> <PageviewsChart data={{ pageviews, uniques }} unit={unit} />
</div> </div>
); );

View File

@ -8,3 +8,10 @@
line-height: 60px; line-height: 60px;
font-weight: 600; font-weight: 600;
} }
.header {
display: flex;
justify-content: space-between;
align-items: center;
margin-bottom: 10px;
}

View File

@ -24,7 +24,7 @@ export function formatTime(val) {
} }
export function formatShortTime(val, formats = ['m', 's'], space = '') { export function formatShortTime(val, formats = ['m', 's'], space = '') {
if (val === 0) { if (val <= 0) {
return `0${formats[formats.length - 1]}`; return `0${formats[formats.length - 1]}`;
} }

View File

@ -10,9 +10,6 @@ import WebsiteList from '../components/WebsiteList';
export default function HomePage({ username }) { export default function HomePage({ username }) {
return ( return (
<Layout> <Layout>
<h2>
You've successfully logged in as <b>{username}</b>.
</h2>
<WebsiteList /> <WebsiteList />
<div> <div>
<PageviewsChart <PageviewsChart