From a2db27894f8b42d796aeb504b3c26ab204bc4fd3 Mon Sep 17 00:00:00 2001 From: Mike Cao Date: Mon, 3 Aug 2020 18:12:28 -0700 Subject: [PATCH] Refactor components and styles. --- components/PageviewsChart.js | 12 +- components/PageviewsChart.module.css | 11 +- components/RankingsChart.js | 57 +++++----- components/RankingsChart.module.css | 3 +- components/WebsiteChart.js | 42 +++---- components/WebsiteChart.module.css | 5 +- components/WebsiteDetails.js | 155 ++++++++++---------------- components/WebsiteList.js | 4 +- components/WebsiteList.module.css | 29 +++++ components/WorldMap.module.css | 1 + lib/db.js | 10 +- lib/session.js | 4 +- pages/api/website/[id]/index.js | 2 +- pages/index.js | 13 --- pages/{[id].js => website/[...id].js} | 8 +- styles/index.css | 17 ++- 16 files changed, 189 insertions(+), 184 deletions(-) rename pages/{[id].js => website/[...id].js} (64%) diff --git a/components/PageviewsChart.js b/components/PageviewsChart.js index 9d601243..b3c2b598 100644 --- a/components/PageviewsChart.js +++ b/components/PageviewsChart.js @@ -66,16 +66,16 @@ export default function PageviewsChart({ label: 'unique visitors', data: data.uniques, lineTension: 0, - backgroundColor: 'rgb(146, 86, 217, 0.4)', - borderColor: 'rgb(122, 66, 191, 0.4)', + backgroundColor: 'rgb(38, 128, 235, 0.4)', + borderColor: 'rgb(13, 102, 208, 0.4)', borderWidth: 1, }, { label: 'page views', data: data.pageviews, lineTension: 0, - backgroundColor: 'rgb(38, 128, 235, 0.4)', - borderColor: 'rgb(13, 102, 208, 0.4)', + backgroundColor: 'rgb(38, 128, 235, 0.2)', + borderColor: 'rgb(13, 102, 208, 0.2)', borderWidth: 1, }, ], @@ -165,7 +165,9 @@ const Tooltip = ({ title, value, label, labelColor }) => (
{title}
-
+
+
+
{value} {label}
diff --git a/components/PageviewsChart.module.css b/components/PageviewsChart.module.css index c378bcbb..9b344849 100644 --- a/components/PageviewsChart.module.css +++ b/components/PageviewsChart.module.css @@ -30,9 +30,14 @@ } .dot { + position: relative; + overflow: hidden; + border-radius: 100%; + margin-right: 8px; + background: #fff; +} + +.color { width: 10px; height: 10px; - border-radius: 100%; - border: 1px solid #b3b3b3; - margin-right: 8px; } diff --git a/components/RankingsChart.js b/components/RankingsChart.js index c445a4fb..cf0ca85c 100644 --- a/components/RankingsChart.js +++ b/components/RankingsChart.js @@ -1,6 +1,7 @@ import React, { useState, useEffect, useMemo } from 'react'; -import { useSpring, animated } from 'react-spring'; +import { useSpring, animated, config } from 'react-spring'; import classNames from 'classnames'; +import CheckVisible from './CheckVisible'; import { get } from 'lib/web'; import { percentFilter } from 'lib/filters'; import styles from './RankingsChart.module.css'; @@ -14,7 +15,6 @@ export default function RankingsChart({ heading, className, dataFilter, - animate = true, onDataLoad = () => {}, }) { const [data, setData] = useState(); @@ -50,43 +50,42 @@ export default function RankingsChart({ } return ( -
-
-
{title}
-
{heading}
-
- {rankings.map(({ x, y, z }) => - animate ? ( - - ) : ( - - ), + + {visible => ( +
+
+
{title}
+
{heading}
+
+ {rankings.map(({ x, y, z }) => ( + + ))} +
)} -
+ ); } -const Row = ({ label, value, percent }) => ( -
-
{label}
-
{value.toFixed(0)}
-
-
{`${percent.toFixed(0)}%`}
-
-
-
-); - -const AnimatedRow = ({ label, value, percent }) => { - const props = useSpring({ width: percent, y: value, from: { width: 0, y: 0 } }); +const Row = ({ label, value, percent, animate }) => { + const props = useSpring({ + width: percent, + y: value, + from: { width: 0, y: 0 }, + config: animate ? config.default : { duration: 0 }, + }); return (
{label}
{props.y.interpolate(n => n.toFixed(0))}
- {props.width.interpolate(n => `${n.toFixed(0)}%`)} - + `${n}%`) }} + /> + + {props.width.interpolate(n => `${n.toFixed(0)}%`)} +
); diff --git a/components/RankingsChart.module.css b/components/RankingsChart.module.css index 76d3cdb8..9e9174ea 100644 --- a/components/RankingsChart.module.css +++ b/components/RankingsChart.module.css @@ -56,11 +56,12 @@ } .percent { + position: relative; width: 50px; color: #6e6e6e; - position: relative; border-left: 1px solid #8e8e8e; padding-left: 10px; + z-index: 1; } .bar { diff --git a/components/WebsiteChart.js b/components/WebsiteChart.js index cdcbdb7c..1e5ab536 100644 --- a/components/WebsiteChart.js +++ b/components/WebsiteChart.js @@ -1,26 +1,26 @@ import React, { useState, useEffect, useMemo, useRef } from 'react'; import classNames from 'classnames'; import PageviewsChart from './PageviewsChart'; -import { get } from 'lib/web'; -import { getDateArray, getDateRange, getTimezone } from 'lib/date'; +import CheckVisible from './CheckVisible'; import MetricsBar from './MetricsBar'; import QuickButtons from './QuickButtons'; -import styles from './WebsiteChart.module.css'; import DateFilter from './DateFilter'; import useSticky from './hooks/useSticky'; +import { get } from 'lib/web'; +import { getDateArray, getDateRange, getTimezone } from 'lib/date'; +import styles from './WebsiteChart.module.css'; export default function WebsiteChart({ websiteId, defaultDateRange = '7day', stickHeader = false, - animate = true, onDateChange = () => {}, }) { const [data, setData] = useState(); const [dateRange, setDateRange] = useState(getDateRange(defaultDateRange)); const { startDate, endDate, unit, value } = dateRange; const [ref, sticky] = useSticky(stickHeader); - const width = useRef(); + const container = useRef(); const [pageviews, uniques] = useMemo(() => { if (data) { @@ -52,16 +52,12 @@ export default function WebsiteChart({ loadData(); }, [websiteId, startDate, endDate, unit]); - useEffect(() => { - width.current = document.querySelector('main').offsetWidth; - }, [sticky]); - return ( - <> +
- - - + + {visible => ( + + + + )} +
- +
); } diff --git a/components/WebsiteChart.module.css b/components/WebsiteChart.module.css index f68aa7de..5076bf47 100644 --- a/components/WebsiteChart.module.css +++ b/components/WebsiteChart.module.css @@ -13,7 +13,7 @@ display: flex; justify-content: space-between; align-items: center; - margin-bottom: 10px; + padding: 10px 0; } .sticky { @@ -21,7 +21,6 @@ top: 0; margin: auto; background: #fff; - padding: 10px 0; border-bottom: 1px solid #e1e1e1; - z-index: 1; + z-index: 2; } diff --git a/components/WebsiteDetails.js b/components/WebsiteDetails.js index 6b963f1b..d157da83 100644 --- a/components/WebsiteDetails.js +++ b/components/WebsiteDetails.js @@ -37,103 +37,69 @@ export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' }) } return ( - <> +
-

{data.label}

- - {visible => ( - - )} - +

{data.label}

+
- - {visible => ( - - )} - +
- - {visible => ( - - )} - +
- - {visible => ( - - )} - +
- - {visible => ( - - )} - +
- - {visible => ( - - )} - +
@@ -141,23 +107,18 @@ export default function WebsiteDetails({ websiteId, defaultDateRange = '7day' })
- - {visible => ( - setCountryData(data)} - animate={visible} - /> - )} - + setCountryData(data)} + />
- +
); } diff --git a/components/WebsiteList.js b/components/WebsiteList.js index 9bc60542..a18afe6b 100644 --- a/components/WebsiteList.js +++ b/components/WebsiteList.js @@ -18,10 +18,10 @@ export default function WebsiteList() { return (
{data && - data.websites.map(({ website_id, website_uuid, label }) => ( + data.websites.map(({ website_id, label }) => (

- + {label}

diff --git a/components/WebsiteList.module.css b/components/WebsiteList.module.css index f52e78b9..cb284497 100644 --- a/components/WebsiteList.module.css +++ b/components/WebsiteList.module.css @@ -1,3 +1,32 @@ .container > div { + padding-bottom: 30px; + border-bottom: 1px solid #e1e1e1; margin-bottom: 30px; } + +.container > div:last-child { + border-bottom: 0; + margin-bottom: 0; +} + +.container a { + position: relative; + color: #2c2c2c; + text-decoration: none; +} + +.container a:before { + content: ''; + position: absolute; + bottom: -2px; + width: 0; + height: 2px; + background: #2680eb; + opacity: 0.5; + transition: width 100ms; +} + +.container a:hover:before { + width: 100%; + transition: width 100ms; +} diff --git a/components/WorldMap.module.css b/components/WorldMap.module.css index c2528038..bf84d697 100644 --- a/components/WorldMap.module.css +++ b/components/WorldMap.module.css @@ -1,4 +1,5 @@ .container { overflow: hidden; position: relative; + background: #fff; } diff --git a/lib/db.js b/lib/db.js index 244a4d2b..8f20b0b5 100644 --- a/lib/db.js +++ b/lib/db.js @@ -39,11 +39,12 @@ export async function runQuery(query) { }); } -export async function getWebsite(website_uuid) { +export async function getWebsite({ website_id, website_uuid }) { return runQuery( prisma.website.findOne({ where: { - website_uuid, + ...(website_id && { website_id }), + ...(website_uuid && { website_uuid }), }, }), ); @@ -77,11 +78,12 @@ export async function createSession(website_id, data) { ); } -export async function getSession(session_uuid) { +export async function getSession({ session_id, session_uuid }) { return runQuery( prisma.session.findOne({ where: { - session_uuid, + ...(session_id && { session_id }), + ...(session_uuid && { session_uuid }), }, }), ); diff --git a/lib/session.js b/lib/session.js index bbd0dd76..53d1c12a 100644 --- a/lib/session.js +++ b/lib/session.js @@ -18,13 +18,13 @@ export default async req => { const country = await getCountry(req, ip); if (website_uuid) { - const website = await getWebsite(website_uuid); + const website = await getWebsite({ website_uuid }); if (website) { const { website_id } = website; const session_uuid = uuid(website_id, hostname, ip, userAgent, os); - let session = await getSession(session_uuid); + let session = await getSession({ session_uuid }); if (!session) { session = await createSession(website_id, { diff --git a/pages/api/website/[id]/index.js b/pages/api/website/[id]/index.js index 0a215219..cb39c63e 100644 --- a/pages/api/website/[id]/index.js +++ b/pages/api/website/[id]/index.js @@ -6,7 +6,7 @@ export default async (req, res) => { const { id } = req.query; - const website = await getWebsite(id); + const website = await getWebsite({ website_id: +id }); return res.status(200).json(website); }; diff --git a/pages/index.js b/pages/index.js index 5d71fffa..11e12934 100644 --- a/pages/index.js +++ b/pages/index.js @@ -1,26 +1,13 @@ import React from 'react'; -import Link from 'next/link'; import { parse } from 'cookie'; import Layout from 'components/Layout'; -import PageviewsChart from 'components/PageviewsChart'; import { verifySecureToken } from 'lib/crypto'; -import { subDays, endOfDay } from 'date-fns'; import WebsiteList from '../components/WebsiteList'; export default function HomePage({ username }) { return ( -
- -
- - Logout 🡒 -
); } diff --git a/pages/[id].js b/pages/website/[...id].js similarity index 64% rename from pages/[id].js rename to pages/website/[...id].js index e9321edd..ede1d709 100644 --- a/pages/[id].js +++ b/pages/website/[...id].js @@ -1,15 +1,19 @@ import React from 'react'; import { useRouter } from 'next/router'; import Layout from 'components/Layout'; -import WebsiteDetails from '../components/WebsiteDetails'; +import WebsiteDetails from '../../components/WebsiteDetails'; export default function DetailsPage() { const router = useRouter(); const { id } = router.query; + if (!id) { + return null; + } + return ( - + ); } diff --git a/styles/index.css b/styles/index.css index 20090acd..aae75718 100644 --- a/styles/index.css +++ b/styles/index.css @@ -9,6 +9,7 @@ body { width: 100%; height: 100%; box-sizing: border-box; + background: #fafafa; } *, @@ -24,8 +25,14 @@ body { height: 100%; } +a, +a:active, +a:visited { + color: #2680eb; +} + header a { - color: #000; + color: #000 !important; text-decoration: none; } @@ -44,6 +51,14 @@ select { border-radius: 4px; } +main { + background: #fff; +} + +.container { + padding: 0 20px; +} + .row { margin-right: 0; margin-left: 0;