Display page views and unique visitors.

This commit is contained in:
Mike Cao 2020-07-28 19:04:45 -07:00
parent bdcdcd9d13
commit ce92c7897d
16 changed files with 162 additions and 44 deletions

View file

@ -15,7 +15,9 @@ export default function DateFilter({ onChange }) {
return (
<select value={selected} onChange={handleChange}>
{filterOptions.map(option => (
<option name={option}>{option}</option>
<option key={option} name={option}>
{option}
</option>
))}
</select>
);

11
components/MetricCard.js Normal file
View file

@ -0,0 +1,11 @@
import React from 'react';
import styles from './MetricCard.module.css';
const MetricCard = ({ value, label }) => (
<div className={styles.card}>
<div className={styles.value}>{value}</div>
<div className={styles.label}>{label}</div>
</div>
);
export default MetricCard;

View file

@ -0,0 +1,16 @@
.card {
display: flex;
flex-direction: column;
justify-content: center;
margin-right: 50px;
}
.value {
font-size: 36px;
line-height: 40px;
font-weight: 600;
}
.label {
font-size: 16px;
}

View file

@ -1,16 +1,9 @@
import React, { useRef, useEffect, useMemo } from 'react';
import React, { useRef, useEffect } from 'react';
import ChartJS from 'chart.js';
import { getLocalTime } from 'lib/date';
export default function PageviewsChart({ data }) {
const canvas = useRef();
const chart = useRef();
const pageviews = useMemo(() => {
if (data) {
return data.pageviews.map(({ t, y }) => ({ t: getLocalTime(t), y }));
}
return [];
}, [data]);
function draw() {
if (!canvas.current) return;
@ -21,11 +14,19 @@ export default function PageviewsChart({ data }) {
data: {
datasets: [
{
label: 'page views',
data: pageviews,
label: 'unique visitors',
data: data.uniques,
lineTension: 0,
backgroundColor: 'rgb(38, 128, 235, 0.1)',
borderColor: 'rgb(13, 102, 208, 0.2)',
backgroundColor: 'rgb(146, 86, 217, 0.2)',
borderColor: 'rgb(122, 66, 191, 0.3)',
borderWidth: 1,
},
{
label: 'page views',
data: data.pageviews,
lineTension: 0,
backgroundColor: 'rgb(38, 128, 235, 0.2)',
borderColor: 'rgb(13, 102, 208, 0.3)',
borderWidth: 1,
},
],
@ -52,6 +53,10 @@ export default function PageviewsChart({ data }) {
},
tooltipFormat: 'ddd M/DD hA',
},
gridLines: {
display: false,
},
stacked: true,
},
],
yAxes: [
@ -59,13 +64,15 @@ export default function PageviewsChart({ data }) {
ticks: {
beginAtZero: true,
},
stacked: true,
},
],
},
},
});
} else {
chart.current.data.datasets[0].data = pageviews;
chart.current.data.datasets[0].data = data.uniques;
chart.current.data.datasets[1].data = data.pageviews;
chart.current.update();
}
}

View file

@ -26,7 +26,7 @@ export default function WebsiteList() {
<DateFilter onChange={handleDateChange} />
{data &&
data.websites.map(({ website_id, label }) => (
<div>
<div key={website_id}>
<h2>{label}</h2>
<WebsiteStats
websiteId={website_id}

View file

@ -1,10 +1,20 @@
import React, { useState, useEffect } from 'react';
import React, { useState, useEffect, useMemo } from 'react';
import PageviewsChart from './PageviewsChart';
import { get } from 'lib/web';
import { getTimezone } from 'lib/date';
import { getDateArray, getTimezone } from 'lib/date';
import WebsiteSummary from './WebsiteSummary';
export default function WebsiteStats({ websiteId, startDate, endDate, unit }) {
const [data, setData] = useState();
const [pageviews, uniques] = useMemo(() => {
if (data) {
return [
getDateArray(data.pageviews, startDate, endDate, unit),
getDateArray(data.uniques, startDate, endDate, unit),
];
}
return [[], []];
}, [data]);
async function loadData() {
setData(
@ -19,7 +29,12 @@ export default function WebsiteStats({ websiteId, startDate, endDate, unit }) {
useEffect(() => {
loadData();
}, [websiteId, startDate, endDate]);
}, [websiteId, startDate, endDate, unit]);
return <PageviewsChart data={data} />;
return (
<div>
<WebsiteSummary data={{ pageviews, uniques }} />
<PageviewsChart data={{ pageviews, uniques }} />
</div>
);
}

View file

@ -0,0 +1,16 @@
import React from 'react';
import MetricCard from './MetricCard';
import styles from './WebsiteSummary.module.css';
function getTotal(data) {
return data.reduce((n, v) => n + v.y, 0);
}
export default function WebsiteSummary({ data }) {
return (
<div className={styles.container}>
<MetricCard label="Views" value={getTotal(data.pageviews)} />
<MetricCard label="Visitors" value={getTotal(data.uniques)} />
</div>
);
}

View file

@ -0,0 +1,3 @@
.container {
display: flex;
}