Skip to content

Commit

Permalink
fix: gross/broken login ux (#326)
Browse files Browse the repository at this point in the history
* fix: gross/broken login ux

* remove Bulma theme reference

* prettier
  • Loading branch information
mark-ignacio committed Jun 19, 2024
1 parent 3626108 commit 7ab54d6
Show file tree
Hide file tree
Showing 6 changed files with 137 additions and 110 deletions.
2 changes: 0 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@ _Gentei_ is a web and Discord application that monitors YouTube channel membersh

## Additional credit

The Bulma color theme used here is derived from the Cosmo theme available at https://github.com/jenil/bulmaswatch.

Gentei v2's Discord avatar is by [@DAIISHORI](https://twitter.com/daiishori)!

Gentei v1's Discord avatar and v1 + v2's favicon is by [@Dakuma_Art](https://twitter.com/Dakuma_Art)!
Expand Down
5 changes: 2 additions & 3 deletions frontend/src/App.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import React, { Fragment } from "react";
import { BrowserRouter, Route, Routes } from "react-router-dom";
// import "./App.scss";
import AppIndex from "./pages/app/AppIndex";
Expand All @@ -13,7 +12,7 @@ import { CssBaseline } from "@mui/material";

function App() {
return (
<Fragment>
<>
<CssBaseline />
<BrowserRouter>
<Routes>
Expand All @@ -29,7 +28,7 @@ function App() {
</Route>
</Routes>
</BrowserRouter>
</Fragment>
</>
);
}

Expand Down
27 changes: 17 additions & 10 deletions frontend/src/components/dashboard/YouTubeLogin.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,19 +3,26 @@ import signInDarkFocusWeb from "../../../src/assets/img/btn_google_signin_dark_f
import signInDarkNormalWeb from "../../../src/assets/img/btn_google_signin_dark_normal_web.png";
import signInDarkPressedWeb from "../../../src/assets/img/btn_google_signin_dark_pressed_web.png";
import { useYouTubeLoginURL } from "../LoginURL";
import { Box, Card, CardContent, Typography } from "@mui/joy";
import { Backdrop } from "@mui/material";
import { useUser } from "../../stores/UserStore";

export function YouTubeLoginOverlay() {
const [store] = useUser();
return (
<div className="overlay is-flex is-justify-content-center is-align-content-center is-align-items-center">
<div className="card">
<div className="card-content content has-text-centered">
<p>
Please connect your YouTube account below to verify memberships.
</p>
<p>(it's the "Sign in with Google" button below)</p>
</div>
</div>
</div>
<Backdrop open sx={{ position: "absolute" }}>
<Card>
<CardContent sx={{ textAlign: "center" }}>
<Typography>
Please connect your YouTube account to verify memberships.
</Typography>
<Typography>
({!store.user ? "after logging in," : null} it's the "Sign in with
Google" button below)
</Typography>
</CardContent>
</Card>
</Backdrop>
);
}

Expand Down
153 changes: 88 additions & 65 deletions frontend/src/pages/Login.tsx
Original file line number Diff line number Diff line change
@@ -1,11 +1,26 @@
import React, { Fragment, ReactNode, useEffect } from "react";
import { SiDiscord } from "react-icons/si";
import { Link, Navigate, useSearchParams } from "react-router-dom";
import {
Link as RouterLink,
Navigate,
useSearchParams,
} from "react-router-dom";
import Footer from "../components/Footer";
import { useDiscordLoginURL, useYouTubeLoginURL } from "../components/LoginURL";
import { LoadState } from "../lib/lib";
import { useUser } from "../stores/UserStore";
import { Typography } from "@mui/joy";
import {
Alert,
Button,
Card,
CardActions,
CardContent,
CircularProgress,
Container,
Grid,
Stack,
Typography,
} from "@mui/joy";

export function LoginDiscord() {
const [search] = useSearchParams();
Expand Down Expand Up @@ -33,31 +48,34 @@ export function LoginDiscord() {
switch (store.discordLoginError?.error_description) {
case `Invalid "code" in request.`:
explainer = (
<Fragment>
<>
The login code given to us by Discord can't be used - this usually
means it expired. Please try again!
</Fragment>
</>
);
break;
default:
explainer = (
<Fragment>
Unhandled error logging in - please try again later.
</Fragment>
);
explainer = <>Unhandled error logging in - please try again later.</>;
break;
}
cardContent = (
<Fragment>
<div className="notification is-danger">{explainer}</div>
<div className="buttons is-centered">
<Link to="/app" className="button is-secondary">
<CardContent>
<Alert color="warning">{explainer}</Alert>
</CardContent>
<CardActions>
<Button
component={RouterLink}
to="/app"
variant="outlined"
color="neutral"
>
Back to app home
</Link>
<a className="button is-primary" href={loginURL!}>
</Button>
<Button component="a" href={loginURL!}>
Try again
</a>
</div>
</Button>
</CardActions>
</Fragment>
);
break;
Expand All @@ -76,20 +94,21 @@ export function LoginDiscord() {
);
}
return (
<section className="section">
<div className="container">
<div className={`columns is-mobile is-centered mt-4 ${columnsClasses}`}>
<div className={`column ${columnClasses}`}>
<div className="card">
<div className="card-content has-text-centered">
{cardContent}
</div>
</div>
</div>
</div>
</div>
<>
<Grid
container
direction="column"
alignItems="center"
justifyContent="center"
mt={4}
mb={4}
>
<Grid xs={12} sm={6}>
<Card>{cardContent}</Card>
</Grid>
</Grid>
<Footer />
</section>
</>
);
}

Expand All @@ -114,19 +133,19 @@ export function LoginYouTube() {
switch (store.youtubeLoginError?.error) {
case "invalid_grant":
explainer = (
<Fragment>
<>
<Typography>
Google says that the token is invalid - please try again.
</Typography>
<Typography>
(This is known to happen when you refresh this page.)
</Typography>
</Fragment>
</>
);
break;
case "YouTube channel belongs to a different user":
explainer = (
<Fragment>
<>
<Typography>
The YouTube channel you tried to log in with belongs to a
different Discord user of Gentei.
Expand All @@ -135,60 +154,64 @@ export function LoginYouTube() {
If you want to associate that channel with your currently logged
in user, sign in as that other user and remove your account.
</Typography>
</Fragment>
</>
);
break;
default:
explainer = (
<Fragment>
<>
<Typography>
Unhandled error logging in - please try again later.
</Typography>
</Fragment>
</>
);
break;
}
cardContent = (
<Fragment>
<div className="notification is-danger">{explainer}</div>
<div className="buttons is-centered">
<Link to="/app" className="button is-secondary">
<>
<CardContent>
<Alert color="warning">{explainer}</Alert>
</CardContent>
<CardActions>
<Button component={RouterLink} to="/app">
Back to app home
</Link>
<a className="button is-primary" href={loginURL!}>
</Button>
<Button component="a" href={loginURL!}>
Try again
</a>
</div>
</Fragment>
</Button>
</CardActions>
</>
);
break;
case LoadState.Succeeded:
return <Navigate to="/app" />;
default:
cardContent = (
<Fragment>
<span>Connecting YouTube...</span>
<div className="mt-2">
<span className="spin icon m-auto">
<span className="spinner"></span>
</span>
</div>
</Fragment>
<>
<CardContent>
<Stack spacing={1}>
<Typography>Connecting your YouTube account...</Typography>
<CircularProgress />
</Stack>
</CardContent>
</>
);
}
return (
<section className="section">
<div className="container">
<div className="columns">
<div className="column">
<div className="card">
<div className="card-content has-text-centered">
{cardContent}
</div>
</div>
</div>
</div>
</div>
</section>
<>
<Grid
container
direction="column"
alignItems="center"
justifyContent="center"
mt={4}
mb={4}
>
<Grid xs={12} sm={6}>
<Card>{cardContent}</Card>
</Grid>
</Grid>
<Footer />
</>
);
}
57 changes: 27 additions & 30 deletions frontend/src/pages/app/UserDashboard.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -5,35 +5,22 @@ import SelfManage from "../../components/dashboard/SelfManage";
import { YouTubeLoginOverlay } from "../../components/dashboard/YouTubeLogin";
import { LoadState } from "../../lib/lib";
import { useUser } from "../../stores/UserStore";
import { Grid } from "@mui/joy";
import { Box, Button, Grid, Stack } from "@mui/joy";
import { useDiscordLoginURL } from "../../components/LoginURL";
import { SiDiscord } from "react-icons/si";

export default function UserDashboard() {
const [store] = useUser();
let loginRequiredOverlay = null;
if (store.user === undefined && store.userLoad > LoadState.Started) {
loginRequiredOverlay = (
<div className="overlay is-flex is-justify-content-center is-align-content-center is-align-items-center">
<div className="message is-info">
<div className="message-body">
<div className="content">
<p>Please sign in or register to view and manage memberships.</p>
<p>
To verify your membership(s), you will have to connect your
YouTube account after registering.
</p>
</div>
</div>
</div>
</div>
);
}
let serversOrLoginNode;
if (store.user === undefined || !store.user.YouTube.Valid) {
serversOrLoginNode = (
<section>
<DiscordServers />
<YouTubeLoginOverlay />
</section>
<Stack spacing={4}>
<Box component="section" sx={{ position: "relative" }}>
<DiscordServers />
<YouTubeLoginOverlay />
</Box>
{!store.user ? <RegisterSignIn /> : null}
</Stack>
);
} else {
serversOrLoginNode = (
Expand All @@ -44,16 +31,26 @@ export default function UserDashboard() {
}
return (
<Grid container rowSpacing={2}>
<Grid xs={12}>
{serversOrLoginNode}
{loginRequiredOverlay}
</Grid>
<Grid xs={12}>{serversOrLoginNode}</Grid>
<Grid xs={12}>
<SelfManage />
</Grid>
<Grid xs={12}>
<AdminServers />
</Grid>
<Grid xs={12}>{!!store.user ? <AdminServers /> : null}</Grid>
</Grid>
);
}

function RegisterSignIn() {
const loginURL = useDiscordLoginURL();
return (
<Box sx={{ textAlign: "center" }}>
<Button
component="a"
href={loginURL || "#"}
startDecorator={<SiDiscord className="spin-me" />}
>
Register / Sign in with Discord
</Button>
</Box>
);
}
3 changes: 3 additions & 0 deletions frontend/src/stores/UserStore.ts
Original file line number Diff line number Diff line change
Expand Up @@ -63,6 +63,9 @@ const actions = {
response = await authedFetchJSON(`${API_BASE_URL}/me`);
} catch (e: any) {
if (e?.message === "Failed to fetch") {
setState({
userLoad: LoadState.Failed,
});
return;
}
throw e;
Expand Down

0 comments on commit 7ab54d6

Please sign in to comment.