aboutsummaryrefslogtreecommitdiffstats
path: root/client/src/ui/Menu.js
diff options
context:
space:
mode:
Diffstat (limited to 'client/src/ui/Menu.js')
-rw-r--r--client/src/ui/Menu.js109
1 files changed, 71 insertions, 38 deletions
diff --git a/client/src/ui/Menu.js b/client/src/ui/Menu.js
index 6f32280..f3e912d 100644
--- a/client/src/ui/Menu.js
+++ b/client/src/ui/Menu.js
@@ -1,17 +1,9 @@
import { h, Fragment } from 'preact';
-import { useState, useEffect } from 'preact/hooks';
+import { useState } from 'preact/hooks';
import cn from 'classnames';
-import { API_PREFIX } from '../config';
+import { useUser, useUserCtx } from '../user';
import css from './css';
-const fetchJSON = async (url) => {
- const res = await fetch(API_PREFIX + url, { credentials: 'include' });
- if (res.status !== 200)
- throw new Error("wrong status");
-
- return res.json();
-};
-
css`
a.discussion {
display: flex;
@@ -52,8 +44,9 @@ a.discussion > a:hover {
}
`;
-const DiscussionLink = ({ id, name, url, attributedTo, user }) => {
- const writable = attributedTo && attributedTo.indexOf(user) > -1;
+const DiscussionLink = ({ id, name, url, attributedTo }) => {
+ const { user } = useUser();
+ const writable = user && attributedTo && attributedTo.indexOf(user.id) > -1;
return (
<a class="discussion" href={`?document=${id}`}>
@@ -79,12 +72,12 @@ ul.discussions > li {
}
`;
-const DiscussionList = ({ discussions, user }) => {
+const DiscussionList = ({ discussions }) => {
return (
<ul class="discussions">
{discussions.map((discussion) => (
<li>
- <DiscussionLink {...discussion} user={user} />
+ <DiscussionLink {...discussion} />
</li>
))}
</ul>
@@ -92,21 +85,73 @@ const DiscussionList = ({ discussions, user }) => {
};
css`
+div.menu div.user {
+ display: flex;
+ align-items: baseline;
+ gap: 1em;
+}
+`;
+const UserMenu = () => {
+ const [showLogin, setLogin] = useState(false);
+ const { state: { user }, dispatch } = useUserCtx();
+
+ if (showLogin) {
+ return (
+ <form class="user" onSubmit={(e) => {
+ e.preventDefault();
+
+ const elem = e.target.elements;
+ const username = elem.namedItem('username').value;
+ const password = elem.namedItem('password').value;
+
+ dispatch({ type: 'login', username, password })
+ .then(
+ () => setLogin(false),
+ (err) => setLogin("error - wrong username/password?"),
+ );
+
+ }}>
+ {showLogin !== true ? <p>{showLogin}</p> : null}
+ <div>
+ <label>username</label>
+ <input name="username" autocomplete="username" required />
+ </div>
+ <div>
+ <label>password</label>
+ <input name="password" autocomplete="password" type="password" required />
+ </div>
+ <input type="submit" value="login" />
+ <button onClick={(e) => { e.preventDefault(); setLogin(false)}}>cancel</button>
+ </form>
+ );
+ }
+
+ return (
+ <div class="user">
+ {user && user.name !== 'Guest'
+ ? (
+ <>
+ <span>logged in as {user.name}</span>
+ <button onClick={() => dispatch({ type: 'logout' })}>log out</button>
+ </>
+ )
+ : (
+ <>
+ <span>not logged in</span>
+ <button onClick={() => setLogin(true)}>log in</button>
+ </>
+ )}
+ </div>
+ );
+};
+
+css`
div.menu {
margin: 1rem 2rem;
}
`;
export const Menu = () => {
- const [user, setUser] = useState(null);
- const [discussions, setDiscussions] = useState([]);
-
- useEffect(() => {
- fetchJSON('/discdag/list')
- .then(({ user, discussions }) => {
- setUser(user ?? null);
- setDiscussions(discussions);
- });
- }, []);
+ const { user, discussions } = useUser();
if (user === null) {
return (
@@ -120,20 +165,8 @@ export const Menu = () => {
return (
<div class="menu">
<h2>Discussions</h2>
- {/*user && user.name !== 'Guest'
- ? (
- <>
- <span>logged in as {user.name}</span>
- <button>log out</button>
- </>
- )
- : (
- <>
- <span>not logged in</span>
- <button>log in</button>
- </>
- )*/}
- <DiscussionList discussions={discussions} user={user?.id} />
+ <UserMenu />
+ <DiscussionList discussions={discussions} />
</div>
);
};