Skip to content

Commit

Permalink
Add context for login state display in nav [#134]
Browse files Browse the repository at this point in the history
* Add <UserDataWrapper> component to base layout to provide access to
  logged in user via React Context
* Wrap username or login link display into <UserOrLoginLink> Client
  Component; add to <Nav> component
  • Loading branch information
genehack committed Nov 1, 2024
1 parent b460fda commit b9fc0b7
Show file tree
Hide file tree
Showing 4 changed files with 85 additions and 11 deletions.
19 changes: 11 additions & 8 deletions static-site/app/layout.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ import {
siteTitle,
siteTitleAlt,
} from "../data/BaseConfig";
import UserDataWrapper from "../components/user-data-wrapper";

import "./styles/browserCompatability.css";
import "./styles/bootstrap.css";
Expand Down Expand Up @@ -68,17 +69,19 @@ export default function RootLayout({
)}
</head>
<body className={lato.variable}>
<Nav />
<main>
{children}
<UserDataWrapper>
<Nav />
<main>
{children}

<Line />
<Line />

<Footer />
<Footer />

<BigSpacer />
</main>
<PlausibleAnalytics />
<BigSpacer />
</main>
<PlausibleAnalytics />
</UserDataWrapper>
</body>
</html>
);
Expand Down
5 changes: 2 additions & 3 deletions static-site/components/nav/index.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import React from "react";
import { groupsApp } from "../../data/BaseConfig";

import NavLogo from "./nav-logo";
import UserOrLoginLink from "./user-or-login-link";

import "./styles.css";

Expand All @@ -21,9 +22,7 @@ export default function Nav(): React.ReactElement {
<a href="https://docs.nextstrain.org">DOCS</a>
<a href="/contact">CONTACT</a>
<a href="/blog/">BLOG</a>
{/* because we need access to the current context, this also
needs to be an encapsulated client component */}
{/* FIXME <UserOrLoginLink> */}
<UserOrLoginLink />
</>
)}
</nav>
Expand Down
19 changes: 19 additions & 0 deletions static-site/components/nav/user-or-login-link.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
"use client";

import React, { useContext } from "react";

import { UserContext } from "../user-data-wrapper";

export default function UserOrLoginLink(): React.ReactElement {
const { user } = useContext(UserContext);
return user ? (
<a href="/whoami">
<span role="img" aria-labelledby="userIcon">
👤
</span>
{` ${user.username}`}
</a>
) : (
<a href="/login">LOGIN</a>
);
}
53 changes: 53 additions & 0 deletions static-site/components/user-data-wrapper/index.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
"use client";

import React, { createContext } from "react";

type User = {
username: string;
};

type Group = {
isPublic: boolean;
name: string;
};

type UserState = {
user: null | User;
groupMemberships: Group[];
};

const initialState: UserState = {
user: null,
groupMemberships: [],
};

export const UserContext = createContext(initialState);

export default class UserDataWrapper extends React.Component<
{ children: React.ReactNode },
UserState
> {
override state = initialState;

override componentDidMount(): void {
this.loadUser();
}

async loadUser(): Promise<void> {
const response = await fetch("/whoami", {
headers: { Accept: "application/json" },
});

const whoami: UserState = await response.json();

this.setState((state) => ({ ...state, ...whoami }));
}

override render(): React.ReactNode {
return (
<UserContext.Provider value={this.state}>
{this.props.children}
</UserContext.Provider>
);
}
}

0 comments on commit b9fc0b7

Please sign in to comment.