Refactor components. Add refresh button.

This commit is contained in:
Mike Cao 2020-08-31 03:53:39 -07:00
parent d0ca0819c6
commit d06c077019
12 changed files with 85 additions and 56 deletions

View file

@ -4,6 +4,7 @@ import classNames from 'classnames';
import ChartJS from 'chart.js';
import styles from './BarChart.module.css';
import { format } from 'date-fns';
import { formatLongNumber } from '../../lib/format';
export default function BarChart({
chartId,
@ -21,7 +22,7 @@ export default function BarChart({
const chart = useRef();
const [tooltip, setTooltip] = useState({});
const renderLabel = (label, index, values) => {
const renderXLabel = (label, index, values) => {
const d = new Date(values[index].value);
const n = records;
@ -40,6 +41,10 @@ export default function BarChart({
}
};
const renderYLabel = label => {
return +label > 1 ? formatLongNumber(label) : label;
};
const renderTooltip = model => {
const { opacity, title, body, labelColors } = model;
@ -82,7 +87,7 @@ export default function BarChart({
tooltipFormat: 'ddd MMMM DD YYYY',
},
ticks: {
callback: renderLabel,
callback: renderXLabel,
minRotation: 0,
maxRotation: 0,
},
@ -96,6 +101,7 @@ export default function BarChart({
yAxes: [
{
ticks: {
callback: renderYLabel,
beginAtZero: true,
},
stacked,
@ -119,7 +125,7 @@ export default function BarChart({
const { options } = chart.current;
options.scales.xAxes[0].time.unit = unit;
options.scales.xAxes[0].ticks.callback = renderLabel;
options.scales.xAxes[0].ticks.callback = renderXLabel;
options.animation.duration = animationDuration;
onUpdate(chart.current);

View file

@ -1,8 +1,9 @@
import React, { useState } from 'react';
import classNames from 'classnames';
import MetricCard from './MetricCard';
import { formatShortTime, formatNumber, formatLongNumber } from 'lib/format';
import Loading from 'components/common/Loading';
import useFetch from 'hooks/useFetch';
import { formatShortTime, formatNumber, formatLongNumber } from 'lib/format';
import styles from './MetricsBar.module.css';
export default function MetricsBar({ websiteId, startDate, endDate, className }) {
@ -18,26 +19,28 @@ export default function MetricsBar({ websiteId, startDate, endDate, className })
setFormat(state => !state);
}
if (!data) {
return null;
}
const { pageviews, uniques, bounces, totaltime } = data;
const { pageviews, uniques, bounces, totaltime } = data || {};
return (
<div className={classNames(styles.bar, className)} onClick={handleSetFormat}>
<MetricCard label="Views" value={pageviews} format={formatFunc} />
<MetricCard label="Visitors" value={uniques} format={formatFunc} />
<MetricCard
label="Bounce rate"
value={pageviews ? (bounces / pageviews) * 100 : 0}
format={n => Number(n).toFixed(0) + '%'}
/>
<MetricCard
label="Average visit time"
value={totaltime && pageviews ? totaltime / (pageviews - bounces) : 0}
format={n => formatShortTime(n, ['m', 's'], ' ')}
/>
{!data ? (
<Loading />
) : (
<>
<MetricCard label="Views" value={pageviews} format={formatFunc} />
<MetricCard label="Visitors" value={uniques} format={formatFunc} />
<MetricCard
label="Bounce rate"
value={pageviews ? (bounces / pageviews) * 100 : 0}
format={n => Number(n).toFixed(0) + '%'}
/>
<MetricCard
label="Average visit time"
value={totaltime && pageviews ? totaltime / (pageviews - bounces) : 0}
format={n => formatShortTime(n, ['m', 's'], ' ')}
/>
</>
)}
</div>
);
}

View file

@ -4,7 +4,7 @@
}
@media only screen and (max-width: 992px) {
.container > div:last-child {
.bar > div:last-child {
display: none;
}
}

View file

@ -1,8 +1,9 @@
import React from 'react';
import CheckVisible from 'components/helpers/CheckVisible';
import BarChart from './BarChart';
import { getDateLength } from '../../lib/date';
export default function PageviewsChart({ websiteId, data, unit, className }) {
export default function PageviewsChart({ websiteId, data, startDate, endDate, unit, className }) {
const handleUpdate = chart => {
const {
data: { datasets },
@ -43,7 +44,7 @@ export default function PageviewsChart({ websiteId, data, unit, className }) {
},
]}
unit={unit}
records={data.pageviews.length}
records={getDateLength(startDate, endDate, unit)}
animationDuration={visible ? 300 : 0}
onUpdate={handleUpdate}
/>

View file

@ -1,38 +1,36 @@
import React from 'react';
import { useRouter } from 'next/router';
import PageHeader from 'components/layout/PageHeader';
import Link from 'components/common/Link';
import Button from 'components/common/Button';
import ActiveUsers from './ActiveUsers';
import Arrow from 'assets/arrow-right.svg';
import styles from './WebsiteHeader.module.css';
import RefreshButton from '../common/RefreshButton';
import ButtonLayout from '../layout/ButtonLayout';
export default function WebsiteHeader({ websiteId, name, showLink = false }) {
export default function WebsiteHeader({ websiteId, title, showLink = false, onRefresh }) {
const router = useRouter();
return (
<PageHeader>
{showLink ? (
<Link href="/website/[...id]" as={`/website/${websiteId}/${name}`} className={styles.title}>
{name}
</Link>
) : (
<div className={styles.title}>{name}</div>
)}
<div className={styles.title}>{title}</div>
<ActiveUsers className={styles.active} websiteId={websiteId} />
{showLink && (
<Button
icon={<Arrow />}
onClick={() =>
router.push('/website/[...id]', `/website/${websiteId}/${name}`, {
shallow: true,
})
}
size="small"
>
<div>View details</div>
</Button>
)}
<ButtonLayout>
<RefreshButton onClick={onRefresh} />
{showLink && (
<Button
icon={<Arrow />}
onClick={() =>
router.push('/website/[...id]', `/website/${websiteId}/${name}`, {
shallow: true,
})
}
size="small"
>
<div>View details</div>
</Button>
)}
</ButtonLayout>
</PageHeader>
);
}