Implement redux.

This commit is contained in:
Mike Cao 2020-08-04 22:45:05 -07:00
parent 9d8a2406e1
commit 5d4ff5cfa4
31 changed files with 341 additions and 85 deletions

View file

@ -1,14 +1,30 @@
import React from 'react';
import Link from 'next/link';
import { useSelector } from 'react-redux';
import classNames from 'classnames';
import Link from 'components/Link';
import styles from './Header.module.css';
export default function Header() {
const user = useSelector(state => state.user);
return (
<header className="container">
<h1>
<Link href="/">
<a>umami</a>
</Link>
</h1>
<header className={classNames(styles.header, 'container')}>
<div className="row align-items-center">
<div className="col">
<Link href="/" className={styles.title}>
umami
</Link>
</div>
{user && (
<div className="col">
<div className={styles.nav}>
<Link href="/">Dashboard</Link>
<Link href="/settings">Settings</Link>
<Link href="/logout">Logout</Link>
</div>
</div>
)}
</div>
</header>
);
}

View file

@ -0,0 +1,25 @@
.header {
display: flex;
height: 80px;
}
.header > div {
flex: 1;
}
.title {
font-size: 30px;
}
.nav {
list-style: none;
display: flex;
justify-content: flex-end;
align-items: center;
}
.nav > * {
font-size: 14px;
font-weight: 600;
margin-left: 40px;
}

View file

@ -3,9 +3,9 @@ import classNames from 'classnames';
import NextLink from 'next/link';
import styles from './Link.module.css';
export default function Link({ href, className, children }) {
export default function Link({ className, children, ...props }) {
return (
<NextLink href={href}>
<NextLink {...props}>
<a className={classNames(styles.link, className)}>{children}</a>
</NextLink>
);

View file

@ -20,7 +20,7 @@ export default function Login() {
const [message, setMessage] = useState();
const handleSubmit = async ({ username, password }) => {
const response = await post('/api/auth', { username, password });
const response = await post('/api/auth/login', { username, password });
if (response?.token) {
await Router.push('/');

View file

@ -3,10 +3,6 @@
}
@media only screen and (max-width: 1000px) {
.container {
padding-bottom: 20px;
}
.container > div:last-child {
display: none;
}

View file

@ -3,6 +3,8 @@
min-height: 430px;
font-size: 14px;
padding: 20px 0;
display: flex;
flex-direction: column;
}
.header {
@ -76,12 +78,14 @@
.body {
position: relative;
flex: 1;
}
.body:empty:before {
content: 'No data available';
display: block;
color: #b3b3b3;
text-align: center;
line-height: 50px;
position: absolute;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
}

9
components/Settings.js Normal file
View file

@ -0,0 +1,9 @@
import React from 'react';
export default function Settings() {
return (
<div>
<h2>Settings</h2>
</div>
);
}

View file

@ -1,3 +1,8 @@
.container {
background: #fff;
padding: 0 30px;
}
.chart {
margin-bottom: 30px;
}

View file

@ -18,23 +18,31 @@ export default function WebsiteList() {
}, []);
return (
<>
<div className={styles.container}>
{data &&
data.websites.map(({ website_id, label }) => (
<div key={website_id} className={styles.website}>
<div className={styles.header}>
<h2>
<Link href={`/website/${website_id}/${label}`} className={styles.title}>
<Link
href="/website/[...id]"
as={`/website/${website_id}/${label}`}
className={styles.title}
>
{label}
</Link>
</h2>
<Link href={`/website/${website_id}/${label}`} className={styles.details}>
<Link
href="/website/[...id]"
as={`/website/${website_id}/${label}`}
className={styles.details}
>
<Icon icon={<Arrow />} /> View details
</Link>
</div>
<WebsiteChart key={website_id} title={label} websiteId={website_id} />
</div>
))}
</>
</div>
);
}

View file

@ -1,3 +1,8 @@
.container {
background: #fff;
padding: 0 30px;
}
.website {
padding-bottom: 30px;
border-bottom: 1px solid #e1e1e1;