Set up the user interface state model and set up the admin user onboarding #283
|
@ -8,6 +8,7 @@ import { WebsocketProvider } from './components/WebsocketProvider';
|
||||||
import { PlayerView } from './views/PlayerView/PlayerView';
|
import { PlayerView } from './views/PlayerView/PlayerView';
|
||||||
import { Admin } from './views/Admin/Admin';
|
import { Admin } from './views/Admin/Admin';
|
||||||
import Candela from './plugins/Candela';
|
import Candela from './plugins/Candela';
|
||||||
|
import { Authentication } from './views/Authentication/Authentication';
|
||||||
|
|
||||||
const TEST_CHARSHEET_UUID = "12df9c09-1f2f-4147-8eda-a97bd2a7a803";
|
const TEST_CHARSHEET_UUID = "12df9c09-1f2f-4147-8eda-a97bd2a7a803";
|
||||||
|
|
||||||
|
@ -35,6 +36,10 @@ const App = ({ client }: AppProps) => {
|
||||||
|
|
||||||
let router =
|
let router =
|
||||||
createBrowserRouter([
|
createBrowserRouter([
|
||||||
|
{
|
||||||
|
path: "/",
|
||||||
|
element: websocketUrl ? <WebsocketProvider websocketUrl={websocketUrl}> <Authentication client={client}> <PlayerView client={client} /> </Authentication> </WebsocketProvider> : <div> </div>
|
||||||
|
},
|
||||||
{
|
{
|
||||||
path: "/gm",
|
path: "/gm",
|
||||||
element: websocketUrl ? <WebsocketProvider websocketUrl={websocketUrl}> <GmView client={client} /> </WebsocketProvider> : <div> </div>
|
element: websocketUrl ? <WebsocketProvider websocketUrl={websocketUrl}> <GmView client={client} /> </WebsocketProvider> : <div> </div>
|
||||||
|
@ -43,10 +48,6 @@ const App = ({ client }: AppProps) => {
|
||||||
path: "/admin",
|
path: "/admin",
|
||||||
element: <Admin client={client} />
|
element: <Admin client={client} />
|
||||||
},
|
},
|
||||||
{
|
|
||||||
path: "/",
|
|
||||||
element: websocketUrl ? <WebsocketProvider websocketUrl={websocketUrl}> <PlayerView client={client} /> </WebsocketProvider> : <div> </div>
|
|
||||||
},
|
|
||||||
{
|
{
|
||||||
path: "/candela",
|
path: "/candela",
|
||||||
element: <CandelaCharsheet client={client} />
|
element: <CandelaCharsheet client={client} />
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
:root {
|
||||||
|
--border-standard: 2px solid black;
|
||||||
|
--border-radius-standard: 4px;
|
||||||
|
--border-shadow-shallow: 1px 1px 2px black;
|
||||||
|
--padding-m: 8px;
|
||||||
|
--margin-s: 4px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
border: var(--border-standard);
|
||||||
|
border-radius: var(--border-radius-standard);
|
||||||
|
box-shadow: var(--border-shadow-shallow);
|
||||||
|
padding: var(--padding-m);
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,24 @@
|
||||||
|
@import '../../design.css';
|
||||||
|
|
||||||
|
.auth {
|
||||||
|
display: flex;
|
||||||
|
justify-content: center;
|
||||||
|
align-items: center;
|
||||||
|
width: 100%;
|
||||||
|
height: 100vh;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth > div {
|
||||||
|
border: var(--border-standard);
|
||||||
|
border-radius: var(--border-radius-standard);
|
||||||
|
padding: var(--padding-m);
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth__input-line {
|
||||||
|
display: flex;
|
||||||
|
justify-content: space-between;
|
||||||
|
}
|
||||||
|
|
||||||
|
.auth__input-line > * {
|
||||||
|
margin: var(--margin-s);
|
||||||
|
}
|
|
@ -0,0 +1,50 @@
|
||||||
|
import React, { PropsWithChildren, ReactNode, useContext, useEffect, useState } from 'react';
|
||||||
|
import { Client } from '../../client';
|
||||||
|
import { assertNever } from '../../plugins/Candela';
|
||||||
|
import './Authentication.css';
|
||||||
|
|
||||||
|
interface AuthenticationProps {
|
||||||
|
client: Client;
|
||||||
|
}
|
||||||
|
|
||||||
|
type AuthState = "NoAdmin" | "Unauthed" | "Authed";
|
||||||
|
|
||||||
|
export const Authentication = ({ client, children }: PropsWithChildren<AuthenticationProps>) => {
|
||||||
|
// No admin password set: prompt for the admin password
|
||||||
|
// Password set, nobody logged in: prompt for login
|
||||||
|
// User logged in: show the children
|
||||||
|
|
||||||
|
let [state, setState] = useState<AuthState>("Unauthed");
|
||||||
|
|
||||||
|
switch (state) {
|
||||||
|
case "NoAdmin": {
|
||||||
|
return <div className="auth">
|
||||||
|
<div className="card">
|
||||||
|
<h1> Welcome to your new Visions VTT Instance </h1>
|
||||||
|
<p> Set your admin password: </p>
|
||||||
|
<input type="password" placeholder="Password" />
|
||||||
|
<input type="submit" value="Submit" />
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
case "Unauthed": {
|
||||||
|
return <div className="auth card">
|
||||||
|
<div className="card">
|
||||||
|
<h1> Welcome to Visions VTT </h1>
|
||||||
|
<div className="auth__input-line">
|
||||||
|
<input type="text" placeholder="Username" />
|
||||||
|
<input type="password" placeholder="Password" />
|
||||||
|
<input type="submit" value="Sign in" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>;
|
||||||
|
}
|
||||||
|
case "Authed": {
|
||||||
|
return <div> {children} </div>;
|
||||||
|
}
|
||||||
|
default: {
|
||||||
|
assertNever(state);
|
||||||
|
return <div></div>;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue